[Chinese ver]
2. Add Two Numbers
轉載請註明原文出處 leonchen1024.com/2018/07/15/…
問題:你將獲得兩個非空 linked lists來表示兩個非負整數。 數字以反向的順序儲存,並且它們的每個節點包含一位數字。 將兩個數字相加並將其以 linked list的形式返回。
你可以假定這兩個數字不包含任何前導零(即不存在首位出現0的情況),除了數字0本身。
輸入 :(2 -> 4 -> 3) + (5 -> 6 -> 4) 輸出 : 7 -> 0 -> 8
方法一:
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;
}
複製程式碼
分析
其實這個問題熟悉一下連結串列的使用和算術的邏輯就可以解決了。按位加過十進一,注意,加法的進位只會是0或者1,因為就算你用兩個最大的數9+9最後也只是進一,進一之後再9+9+1也只會得到19,還是進一。所以主要的邏輯就是兩個數的和sum/10得到的是進位,sum%10得到的是本位的數。dummyHead是一個假的資料頭,用來做一個初始化,不使用也是可以的,但是在內部邏輯中就需要自己在處理第一位和後續的位數的邏輯區別。 注意有幾種特殊情況。1.其中一個list的長度比另一個要長。2.其中一個list為空。3.加到最後一位時仍然還有進位
時間複雜度: O(max(m,n)).總共迴圈m和n中的最大次數。 空間複雜度 : O(max(m,n)).我們得到的新的list 的長度是m,n中最大長度,加上一個假資料頭。
方法二
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode ln1 = l1, ln2 = l2, head = null, node = null;
int carry = 0, remainder = 0, sum = 0;
head = node = new ListNode(0);
while(ln1 != null || ln2 != null || carry != 0) {
sum = (ln1 != null ? ln1.val : 0) + (ln2 != null ? ln2.val : 0) + carry;
carry = sum / 10;
remainder = sum % 10;
node = node.next = new ListNode(remainder);
ln1 = (ln1 != null ? ln1.next : null);
ln2 = (ln2 != null ? ln2.next : null);
}
return head.next;
}
}
複製程式碼
這個是別人的做法,居然能夠比方法一快了許多,說實話,其實這兩個方法在整體思路上是差不多的,至於為什麼會比前者快那麼多我覺的是方法一在迴圈中不斷新建了x,y等物件,由於計時時用了成千上百的例子驗證所以導致了20ms左右的差距。以上純屬個人看法,如果你有更正確的想法,或者哪裡有有關這種差距的論證,請告訴我。謝謝。
About Me
我的部落格 leonchen1024.com
我的 GitHub github.com/LeonChen102…
微信公眾號