LeetCode两数相加

123 阅读3分钟

一、两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

 

示例 1:

输入: l1 = [2,4,3], l2 = [5,6,4]
输出: [7,0,8]
解释: 342 + 465 = 807.

示例 2:

输入: l1 = [0], l2 = [0]
输出: [0]

示例 3:

输入: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出: [8,9,9,9,0,0,0,1]

 

提示:

  • 每个链表中的节点数在范围 [1, 100] 内
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

二、解题思路:

1.迭代法

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int val=0, ListNode next=null) {
 *         this.val = val;
 *         this.next = next;
 *     }
 * }
 */
public class Solution {
    public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {
        //记录每次提取十位上数的值
        int next1 = 0;
        //记录每次要相加的数
        int total = 0;
        //创建一个新节点
        ListNode dummy = new ListNode();
        //新节点复制给另一个新节点,后续可以拿cur节点进行移动,而不动dummy节点,cur可以让我知道当前的指针是在哪
        ListNode cur = dummy;
        //循环遍历进行操作,当其中有一个链表走到头了我们就跳出循环
        while (l1 != null && l2 != null) {
            //total记录的是每次两数相加+每次两数相加之后有十位数的值要提取的值
            total = l1.val + l2.val + next1;
            //可移动节点的引用指向由个位数上的值所创建的链表节点,也就是把每次的个位数的值作为最终结果节点的每一项值
            cur.next = new ListNode(total % 10);
            //获取的是十位数上的值
            next1 = total / 10;
            //移动到下一个节点去
            l1 = l1.next;
            l2 = l2.next;
            //当前可移动节点指向下一个可移动节点
            cur = cur.next;
        }
        //判断l1是否走到头,如果没有,那就是l2走到头了
        while (l1 != null) {
            total = l1.val + next1;
            cur.next = new ListNode(total % 10);
            next1 = total / 10;
            l1 = l1.next;
            cur = cur.next;
        }
        //l2没有走完的情况下,同时l1走完了
        while (l2 != null) {
            total = l2.val + next1;
            cur.next = new ListNode(total % 10);
            next1 = total / 10;
            l2 = l2.next;
            cur = cur.next;
        }

        //next1==0,说明l1,l2都走完了,如果不等于0说明,此时还有一个数没有加进来,需要再次加入到链表中
        if (next1 != 0) {
            //创建一个新的节点,存储最后的十位数
            cur.next = new ListNode(next1);
        }
        //注意返回的是节点的next
        return dummy.next;
    }
}

2.递归法

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int val=0, ListNode next=null) {
 *         this.val = val;
 *         this.next = next;
 *     }
 * }
 */
public class Solution {
    public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {
        //先记录两次节点的数之和
         int total = l1.val + l2.val;
         //记录十位数的值,后续要进位
        int next1 = total / 10;
        //以个位数上的值创建一个新链表节点
        ListNode res = new ListNode(total%10);
        //循环判断,l1,l2是否已经遍历完,或者next1是否为0,为0表示l1,l2同时走完,不为0表示某一个走完都有可能
        if (l1.next != null || l2.next != null || next1 != 0) {
            //下一个节点的指向不为null,则指向下一个节点,为null,则表示当前链表走完了,就以0位值创建一个新链表
            l1 = l1.next!=null ? l1.next : new ListNode(0);
            l2 = l2.next!=null ? l2.next : new ListNode(0);
            //将每次需要提取的十位数加入l1链表当前项中,加入l2链表其实也是一样的
            l1.val += next1;
            //改变可移动链表的指向,每一次的调用,里面的l1,l2的值都会是下一项的值
            res.next = AddTwoNumbers(l1, l2);
        }
        //直到两个链表都遍历完,返回链表
        return res;
    }
}