Tuesday, September 12, 2017

2. Add Two Numbers

二刷 07/2022
Version #2 Recursion
Time O(N)
Space O(N) for system stack
Runtime: 2 ms, faster than 99.28% of Java online submissions for Add Two Numbers.
Memory Usage: 48.1 MB, less than 26.21% of Java online submissions for Add Two Numbers.

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        return addHelper(l1, l2, 0);
    }
    
    private ListNode addHelper(ListNode l1, ListNode l2, int carry) {
        if (l1 == null && l2 == null && carry == 0) {
            return null;
        }
        carry += l1 == null ? 0 : l1.val;
        carry += l2 == null ? 0 : l2.val;
        ListNode node = new ListNode(carry % 10);
        node.next = addHelper(l1 == null ? null : l1.next, l2 == null ? null : l2.next, carry / 10);
        return node;
    }
}


Version #1 Iteration
自己手写的方法
只要有一个list是null以后就停,然后加另外一个非null的list
没有注意到的bug是最后两个list都是null以后,carry还有可能不是0,需要继续加carry

90.76 %

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //    (2 -> 4 -> 3 -> 6)
        // +  (5 -> 6 -> 4)
        // =   7 -> 0 -> 8
        // 342 + 465 = 807
        if (l1 == null) return l2;
        if (l2 == null) return l1;
        ListNode dummy = new ListNode(0);
        ListNode curr = dummy;
        int carry = 0;
        while (l1 != null && l2 != null) {
            int sum = l1.val + l2.val + carry;
            curr.next = new ListNode(sum % 10);
            carry = sum / 10;
            curr = curr.next;
            l1 = l1.next;
            l2 = l2.next;
        }
        if (l1 == null && l2 == null) {
            if (carry != 0) curr.next = new ListNode(carry);
            return dummy.next;
        } else if (l1 != null) {
            addTail(curr, l1, carry);
        } else {
            addTail(curr, l2, carry);
        }
        return dummy.next;
    }
    private void addTail(ListNode curr, ListNode l, int carry) {
        while (l != null) {
            curr.next = new ListNode((l.val + carry) % 10);
            carry = (l.val + carry) / 10;
            l = l.next;
            curr = curr.next;
        }
        if (carry != 0) curr.next = new ListNode(carry);
    }
}

Version #2

写起来非常简洁,但是效率没有那么高
只要l1 != null || l2 != null || sum != 0 就不出loop
 63.13 %
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode sentinel = new ListNode(0);
        int sum = 0;
        ListNode curr = sentinel;
     
        while (l1 != null || l2 != null || sum != 0) {
            if (l1 != null) {
                sum += l1.val;
                l1 = l1.next;
            }
            if (l2 != null) {
                sum += l2.val;
                l2 = l2.next;
            }
            curr.next = new ListNode(sum % 10);
            sum = sum / 10; // carry to next digit
            curr = curr.next;
        }
        return sentinel.next;
    }
}

三刷
不用dummy node的version2

Runtime: 1 ms, faster than 100.00% of Java online submissions for Add Two Numbers.
Memory Usage: 39.3 MB, less than 50.00% of Java online submissions for Add Two Numbers.
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode p1 = l1, p2 = l2;
        ListNode head = null;
        ListNode curr = null;
        int carry = 0;
        // 2 4 3
        // 9 9 9 9
        //head
        //  curr
        // 1 4
        while (p1 != null || p2 != null || carry != 0) {
            int sum = carry;
            sum += p1 == null ? 0 : p1.val;
            sum += p2 == null ? 0: p2.val;
            carry = sum / 10;
            sum = sum % 10;
            ListNode node = new ListNode(sum);
            if (head == null) {
                head = node;
                curr = node;
            } else {
                curr.next = node;
                curr = curr.next;
            }
            if (p1 != null) {
                p1 = p1.next;
            }
            if (p2 != null) {
                p2 = p2.next;
            }
        }
        return head;
    }
}

No comments:

Post a Comment