LeetCode Add Two Numbers题解

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

我只想说,优秀的代码看着真的好舒服。。。
先给出我自己写的代码,再给出官方题解,体验一下小白与大牛的区别。。。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public static int c;
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        c = 0;
        if(l1.val == 0 && l1.next == null && l2.val == 0 && l2.next == null){
            ListNode root = new ListNode(0);
            root.next = null;
            return root;
        }
        ListNode root = addList(l1,l2);
        return root;

    }

    public static ListNode addList(ListNode list1, ListNode list2){
        if(list1 == null && list2 == null){
            if(c == 0){
                return null;
            }else{
                ListNode root = new ListNode(c);
                root.next = null;
                return root;
            }
        }
       else if(list1 == null && list2 != null){
            int sum = c + list2.val;
            c = sum / 10;
            ListNode root = new ListNode(sum % 10);
            if(c == 0){
                root.next = list2.next;
            }else{
                ListNode left = new ListNode(0);
                left.next = null;
                root.next = addList(left,list2.next);
            }
            return root;
        }
       else if(list1 != null && list2 == null){
            int sum = c + list1.val;
            c = sum / 10;
            ListNode root = new ListNode(sum % 10);
            if(c == 0){
                root.next =list1.next;
            }else{
                ListNode left = new ListNode(0);
                left.next = null;
                root.next = addList(left,list1.next);
            }
            return root;
        }
        int a = list1.val;
        int b = list2.val;
        int sum = a + b + c;
        c = sum / 10;
        ListNode root = new ListNode(sum % 10);
        root.next = addList(list1.next,list2.next);
        return root;
    }
}

接下来的代码真的是非常地清晰简洁,也让我深深地感受到了自己的不足与差距.

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    ListNode dummyHead = new ListNode(0);
    ListNode p = l1, q = l2, curr = dummyHead;
    int carry = 0;
    while (p != null || q != null) {
        int x = (p != null) ? p.val : 0;
        int y = (q != null) ? q.val : 0;
        int sum = carry + x + y;
        carry = sum / 10;
        curr.next = new ListNode(sum % 10);
        curr = curr.next;
        if (p != null) p = p.next;
        if (q != null) q = q.next;
    }
    if (carry > 0) {
        curr.next = new ListNode(carry);
    }
    return dummyHead.next;
}

Solution

Intuition

Keep track of the carry using a variable and simulate digits-by-digits sum starting from the head of list, which contains the least-significant digit.

Illustration of Adding two numbers

Figure 1. Visualization of the addition of two numbers: 342 + 465 = 807342+465=807.
Each node contains a single digit and the digits are stored in reverse order.

Algorithm

Just like how you would sum two numbers on a piece of paper, we begin by summing the least-significant digits, which is the head of l1l1 and l2l2. Since each digit is in the range of 0 \ldots 90…9, summing two digits may “overflow”. For example 5 + 7 = 125+7=12. In this case, we set the current digit to 22 and bring over the carry = 1carry=1 to the next iteration. carrycarry must be either 00 or 11 because the largest possible sum of two digits (including the carry) is 9 + 9 + 1 = 199+9+1=19.

The pseudocode is as following:

Initialize current node to dummy head of the returning list.
Initialize carry to 00.
Initialize pp and qq to head of l1l1 and l2l2 respectively.
Loop through lists l1l1 and l2l2 until you reach both ends.
Set xx to node pp’s value. If pp has reached the end of l1l1, set to 00.
Set yy to node qq’s value. If qq has reached the end of l2l2, set to 00.
Set sum = x + y + carrysum=x+y+carry.
Update carry = sum / 10carry=sum/10.
Create a new node with the digit value of (sum \bmod 10)(summod10) and set it to current node’s next, then advance current node to next.
Advance both pp and qq.
Check if carry = 1carry=1, if so append a new node with digit 11 to the returning list.
Return dummy head’s next node.
Note that we use a dummy head to simplify the code. Without a dummy head, you would have to write extra conditional statements to initialize the head’s value.

Take extra caution of the following cases:

Test case Explanation
l1=[0,1]l1=[0,1]
l2=[0,1,2]l2=[0,1,2] When one list is longer than the other.
l1=[]l1=[]
l2=[0,1]l2=[0,1] When one list is null, which means an empty list.
l1=[9,9]l1=[9,9]
l2=[1]l2=[1] The sum could have an extra carry of one at the end, which is easy to forget.
Complexity Analysis

Time complexity : O(\max(m, n))O(max(m,n)). Assume that mm and nn represents the length of l1l1 and l2l2 respectively, the algorithm above iterates at most \max(m, n)max(m,n) times.

Space complexity : O(\max(m, n))O(max(m,n)). The length of the new list is at most \max(m,n) + 1max(m,n)+1.

Follow up

What if the the digits in the linked list are stored in non-reversed order? For example:

(3 \to 4 \to 2) + (4 \to 6 \to 5) = 8 \to 0 \to 7 (3→4→2)+(4→6→5)=8→0→7

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值