1. 程式人生 > >LeetCode-Algorithms #002 Add Two Numbers, Database #176 Second Highest Salary

LeetCode-Algorithms #002 Add Two Numbers, Database #176 Second Highest Salary

LeetCode-Algorithms #002 Add Two Numbers

給定兩個非空的以連結串列結構表示的非負整數, 這個結構長這樣:

1 public class ListNode {
2     int val;
3     ListNode next;
4     ListNode(int x) { val = x; }
5 }

這個結構中從低位到高位由外向記憶體儲, 每一層儲存一位數, 題目要求把給定的兩個數求和, 然後用同樣的結構返回結果.

我的思路:

作為一個頭腦淳樸(簡單)的人, 我還是本能的想, 把這兩個數取出來, 加一加, 然後存回去就好了, 事實也是這麼做了

提交程式碼...

執行超時...

是的, 看來蠢人不配通過提交, 這種做法應該是慢得令人髮指了.

那麼, 只好換個想法, 既然這個結構是個位數存在最外面, 一層一層向裡進位, 那麼我們也就一層一層從外往裡加就好了, 嘗試一下:

 1 class Solution {
 2     public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
 3         //先建立一個ListNode作為答案
 4         ListNode ans = new ListNode(0);
 5         //再建立另一個引用指向同一個物件
 6         ListNode temp = ans;
7 //當l1和l2內層都不為空的時候 8 while (l1.next != null && l2.next != null) { 9 //計算當前層的和:l1和l2該位的值加上上一位的進位 10 int sum = l1.val + l2.val + temp.val; 11 //因為l1和l2內層都不為空, 使l1和l2都等於其內層 12 l1 = l1.next; 13 l2 = l2.next; 14 //
對和取10的餘數, 獲得結果中這一位的值 15 int val = sum % 10; 16 //把和除以10, 獲得進位的值 17 int carry = sum / 10; 18 //對temp賦值 19 temp.val = val; 20 //把進位的值新增到temp的內層 21 temp.next = new ListNode(carry); 22 //使temp的引用向內指一層 23 temp = temp.next; 24 } 25 //上面的迴圈結束後, 只剩下三種可能, 26 //1. l1.next不為null 27 //2. l2.next不為null 28 //3. l1.next,l2.next都為null 29 30 //在第一種情況下, l2.next雖然為null, 但l2.val還沒有被加入最後的結果中 31 while (l1.next != null) { 32 //所以, 我們還是令三者相加 33 int sum = l1.val + l2.val + temp.val; 34 //但是在第一次加過之後就令l2.val = 0, 以免影響後面的迴圈 35 l2.val = 0; 36 //之後l2就不用管了, 令l1等於其內層 37 l1 = l1.next; 38 //後面的部分和第一個迴圈意思一樣 39 int val = sum % 10; 40 int carry = sum / 10; 41 temp.val = val; 42 temp.next = new ListNode(carry); 43 temp = temp.next; 44 } 45 46 //第二種情況下和上面一樣 47 while (l2.next != null) { 48 int sum = l1.val + l2.val + temp.val; 49 l1.val = 0; 50 l2 = l2.next; 51 int val = sum % 10; 52 int carry = sum / 10; 53 temp.val = val; 54 temp.next = new ListNode(carry); 55 temp = temp.next; 56 } 57 58 //到了這裡l1.next和l2.next都為null, 但l1.val和l2.val至少還有一個沒有加入最後的結果中, 59 //也有可能兩個都沒有, 因此還要最後再做一次 60 int sum = l1.val + l2.val + temp.val; 61 int val = sum % 10; 62 int carry = sum / 10; 63 temp.val = val; 64 //最後這次要判斷一下,只有要進位的值不為零的情況下才進位, 否則最後的結果可能會多一個0出來 65 if(carry != 0) { 66 temp.next = new ListNode(carry); 67 } 68 //返回結果 69 return ans; 70 } 71 }

過程中其實碰到了不少預想之外的問題, 感覺寫得也比較囉嗦, 但是總歸是順利實現了:

 測試一下大致是個平均水平, 和第一梯隊差距倒是不算太過明顯, 不過看一看強者的提交, 還是讓人心碎:

 1 class Solution {
 2    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
 3         int carry = 0;
 4         ListNode p = l1;
 5         ListNode q = l2;
 6         ListNode end = l1;
 7         while (p != null || q != null) {
 8             int sum = carry;
 9             if (p!= null && p.next == null) end = p;
10             if (q != null) sum += q.val;
11             if (p != null) sum += p.val;
12             int remainder = sum % 10;
13             carry = sum / 10;            
14             if (p!= null) {
15                 p.val = remainder;
16             } else {
17                 end.next = new ListNode(remainder);
18                 end = end.next;                 
19             }
20             if (p != null) p = p.next;
21             if (q != null) q = q.next;            
22         }
23         if (carry != 0) end.next = new ListNode(carry);
24         return l1;
25     }
26 }

總體思路上有一些相通之處(所以也就沒有額外加註釋), 但是完成質量就是天差地別了