LeetCode(2) ---- 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.

樣例:Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8

翻譯:給你兩個鏈表,然后他們的反序是一個數字(正序2也就是個位,4是十位,3是百位,然后計算他們的倆的和,和輸出也是反序,并且是一個鏈表形式

My View

我的想法是把鏈表表示的數先算出來,然后兩者相加得出答案之后轉換為鏈表,由于結果轉化為鏈表的那部分出現了一點問題,最后也沒搭理,幾天過去了竟然不想再寫,直接去solution了

solution

官方給的示意圖:


Figure 1. Visualization of the addition of two numbers: 342 + 465 = 807.
Each node contains a single digit and the digits are stored in reverse order.
到這里可能已經很深刻的理解題目的意思了。
首先我們考慮單獨相加的方法,從l1和l2的鏈表頭開始,2+5 = 7,4+6 = 10,10的話就會有進位,作為carry(攜帶)送給高位,也就是3+4+1 = 8;
那么在這里carry只可能是0或者1,這是符合我們數學邏輯的。

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;
       //計算實際值(添加carry之后) 
        int sum = carry + x + y;
       //判斷有沒有進位
        carry = sum / 10;
       //添加去除carry位的值
        curr.next = new ListNode(sum % 10);
        //移動節點
        curr = curr.next;
        if (p != null) p = p.next;
        if (q != null) q = q.next;
    }
   //如果到循環結束了還余下一個carry = 1,那么就得新建一個高位,
   可以參考l1=[9,9] ,l2=[1] 這種情況
    if (carry > 0) {
        curr.next = new ListNode(carry);
    }
   //最后返回dummyHead的下一個節點,(因為第一個節點是0,,java很坑吧)
    return dummyHead.next;
}

上述算法的時間復雜和空間復雜都是O(max(m,n)),因為只有一層循環,
所以取決于鏈表最大長度。

正當試著提交這份代碼的時候,系統竟然判定超時,不太理解系統給的方法竟然會超時……

然后去淘discuss,發現大部分人的方法是如下的:

  public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //在定義地方和上面的一致
        ListNode c1 = l1;
        ListNode c2 = l2;
        ListNode sentinel = new ListNode(0);
        ListNode d = sentinel;
        int sum = 0;
       //循環也是一樣的
        while (c1 != null || c2 != null) {
           //這里直接用sum來儲存carry和node_sum值  
            sum /= 10;
            if (c1 != null) {
                sum += c1.val;
                c1 = c1.next;
            }
            if (c2 != null) {
                sum += c2.val;
                c2 = c2.next;
            }
            d.next = new ListNode(sum % 10);
            d = d.next;
        }
      //這里其實和方法一一樣  
      if (sum / 10 == 1)
            d.next = new ListNode(1);
        return sentinel.next;
    }

著實看不懂他倆差別在哪,除了carry與sum合并為一個之外,有知道的寶寶么?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容