# 445.两个链表相加

# 题目

给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。 你可以假设除了数字 0 之外,这两个数字都不会以零开头。

进阶:如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。

示例
输入:(7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 8 -> 0 -> 7

# 解法

由于需要从低位开始加,然后进位。 因此可以采用栈来简化操作。 依次将两个链表的值分别入栈 stack1 和 stack2,然后相加入栈 stack,进位操作用一个变量 carried 记录即可。 最后根据 stack 生成最终的链表即可。

TIP

也可以先将两个链表逆置,然后相加,最后将结果再次逆置。

# 关键点解析

栈的基本操作 carried 变量记录进位 循环的终止条件设置成stack.length > 0 可以简化操作 注意特殊情况, 比如 1 + 99 = 100

# 具体代码

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function(l1, l2) {
    let m = [];
    let n = [];
    let k = [];
    let cur1 = l1;
    let cur2 = l2;
    let jw = 0;
    while(cur1){
        m.push(cur1.val)
        cur1 = cur1.next
    }
    while(cur2){
        n.push(cur2.val)
        cur2 = cur2.next
    }
    let ans = null
    while(m.length > 0 || n.length > 0){
        let x = Number(m.pop()) || 0
        let y = Number(n.pop()) || 0
        k.push((x+y+jw)%10)
        let cur = (x+y+jw)%10
        if(x+y+jw >= 10){
            jw = 1
        }else{
            jw = 0
        }
        
        let curnode = new ListNode(cur)
        curnode.next = ans
        ans = curnode
    }
    let l = new ListNode(1)
    if(jw == 1){
        l.next = ans
        return l
    }
    return ans
    // if(jw == 1){
    //     k.push(1)
    // }
    // const dummy = {};

    // let current = dummy;
  
    // while (k.length > 0) {
    //   current.next = {
    //     val: k.pop(),
    //     next: null
    //   };
  
    //   current = current.next;
    // }
    // console.log(dummy.next)
    // return dummy.next;
};

# 补链表逆转

  • 好理解的双指针 定义两个指针: prepre 和 curcur ;prepre 在前 curcur 在后。 每次让 prepre 的 nextnext 指向 curcur ,实现一次局部反转 局部反转完成之后, prepre 和 curcur 同时往前移动一个位置 循环上述过程,直至 prepre 到达链表尾部

  • 代码

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* cur = NULL, *pre = head;
        while (pre != NULL) {
            ListNode* t = pre->next;
            pre->next = cur;
            cur = pre;
            pre = t;
        }
        return cur;
    }
};
  • 简洁的递归 使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,记作 retret . 此后,每次函数在返回的过程中,让当前结点的下一个结点的 nextnext 指针指向当前节点。 同时让当前结点的 nextnext 指针指向 NULLNULL ,从而实现从链表尾部开始的局部反转 当递归函数全部出栈后,链表反转完成。

  • 代码

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == NULL || head->next == NULL) {
            return head;
        }
        ListNode* ret = reverseList(head->next);
        head->next->next = head;
        head->next = NULL;
        return ret;
    }
};
  • 妖魔化的双指针 原链表的头结点就是反转之后链表的尾结点,使用 headhead 标记 . 定义指针 curcur,初始化为 headhead . 每次都让 headhead 下一个结点的 nextnext 指向 curcur ,实现一次局部反转 局部反转完成之后,curcur 和 headhead 的 nextnext 指针同时 往前移动一个位置 循环上述过程,直至 curcur 到达链表的最后一个结点 .

  • 代码

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == NULL) { return NULL; }
        ListNode* cur = head;
        while (head->next != NULL) {
            ListNode* t = head->next->next;
            head->next->next = cur;
            cur = head->next;
            head->next = t;
        }
        return cur;
    }
};

参考链接 (opens new window)