两个链表相加

两个链表相加

给定两个链表的头节点head1和head2,
认为从左到右是某个数字从低位到高位,返回相加之后的链表
例子:4->3->6 2->5->3
返回:6->8->9
解释:634 + 352 = 986
 
4->3->6 的意思是这代表一个数,个位数是4,十位数是3,百位数是6,所以代表634.
 
例子草图:
思路是什么?
1.先遍历两个链表,把较长的重定位下,找到较长的链表的头,较短链表的头。
2.整个过程分三步走:
1)遍历到的节点,长链表也有,短链表也有
2)遍历到的节点,长链表有,短链表已经无了
3)遍历到的节点,长链表无,短链表也无。
 
如下图所示:
遍历3,7、 4,9、 6,7 的时候属于第一阶段。
遍历1的时候,属于第二阶段。
遍历1后面没有东西了,属于第三阶段。
这三个阶段都有讲究,举个例子:
第1阶段遍历的时候,3 和 7,两数相加可能会产生进位。
4和9相加,而且加上前面进位,4+9+1=14,得知这个节点的值一定是4,而且进位继续维持1.
同理,6和7相加,加进位1,得到该节点值一定是4,而且继续维持进位1.
第一个阶段完成。
 
第二阶段:长链表有,短链表无,此时只剩下长链表节点,和进位信息。
当前节点值1 + 进位1 ,得到该节点值为2,而且进位信息归零。
在第三阶段的时候,如果发现进位信息是0,可以返回了。
 
再看个例子:
第一阶段完成。
 
第二阶段:只有长链表有的阶段:
第三阶段:进位如果是0,前面不补节点。
 
第三阶段是非常关键的,前面两个阶段都完成了,如果还有进位信息,要补个1:
 
代码如下:
而且新值生成的时候,不是创建新链表,而是把老的长链表的值修改下。结果不额外生成链表了,而是压到长链表里面去,最后看长链表要不要补单独的一个新节点。
 
package com.cy.class04;

/**
 * 两个链表相加
 */
public class Code05_AddTwoNumbers {

    public static class ListNode {
        public int val;
        public ListNode next;

        public ListNode(int value) {
            this.val = value;
        }
    }

    /**
     * 变量last的作用:
     * 第三阶段curl和curs都走到最后了,如果还有进位信息,要产生一个进位1
     * 但之前的节点在哪呢?因为要将之前的节点的next指向新创建的1.
     * 之前的节点已经找不到了,因为curl和curs都走到null了,谁的next指针去指向这个新节点1呢?
     * 最后一个不是null的节点去指向这个1
     * 这就是last的作用。
     *
     * last一直跟踪curl,就为了最后挂节点1的时候,知道挂在哪。
     */
    public static ListNode addTwoNumbers(ListNode head1, ListNode head2) {
        int len1 = listLength(head1);
        int len2 = listLength(head2);

        /**
         * l: 较长链表的头
         * s: 较短链表的头
         */
        ListNode l = len1 >= len2 ? head1 : head2;
        ListNode s = l == head1 ? head2 : head1;
        ListNode curL = l;
        ListNode curS = s;
        ListNode last = curL;
        int carry = 0;
        int curNum = 0;

        //第一阶段
        while (curS != null) {
            curNum = curL.val + curS.val + carry;
            curL.val = curNum % 10;
            carry = curNum / 10;
            last = curL;
            curL = curL.next;
            curS = curS.next;
        }

        //第二阶段
        while (curL != null) {
            curNum = curL.val + carry;
            curL.val = curNum % 10;
            carry = curNum / 10;
            last = curL;
            curL = curL.next;
        }

        //第三阶段
        if (carry != 0) {
            last.next = new ListNode(1);
        }
        return l;
    }

    /**
     * 求链表长度
     */
    public static int listLength(ListNode head) {
        int len = 0;
        while (head != null) {
            head = head.next;
            len++;
        }
        return len;
    }
}
 
 
 
 
 
 
 
 
--
posted on 2025-05-02 15:13  有点懒惰的大青年  阅读(64)  评论(0)    收藏  举报