1. 程式人生 > >Problem 02. add-two-numbers

Problem 02. add-two-numbers

Problem 02. add-two-numbers

題目描述

  • 給出兩個非空的連結串列用來表示兩個非負的整數。其中,它們各自的位數是按逆序的方式儲存的,並且它們的每一個節點只能儲存一位數字。

  • 如果,我們將這兩個數相加起來,則會返回一個新的連結串列來表示它們的和。

  • 可以假設除了0之外,這兩個數都不會以0開頭。

  • 示例:

    輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
    輸出:7 -> 0 -> 8
    原因:342 + 465 = 807

解題思路

  • 看完題目,最初的想法就是先把連結串列中的資料取出來,分別轉換成對應整數,將兩個整數相加後再轉換到連結串列中。寫完程式碼後運行了一下,居然是錯的???才發現連結串列中的整數是逆序儲存的(審題!審題!)。逆序就逆序,那我就先把兩個整數翻轉一下,相加後再翻轉,然後放進連結串列裡不就行了?實現是實現了,不過不知道為啥一直有bug,可是我覺得思路沒錯啊。。。(後面有時間再來研究一下到底哪裡有問題。。)

  • 感覺上面的思路太繁瑣,實現起來也麻煩。還是直接在兩個連結串列上進行加法操作吧(這應該是這道題目的初衷,因為它在連結串列中逆序儲存,兩個連結串列頭就是對齊的,就像我們列豎式計算時從個位開始對齊)。那麼我們就從連結串列l1和l2的表頭開始進行加法運算,將對應位置的兩個數字進行加和,然後判斷是否有進位的情況。設定一個 carry 來儲存進位的情況,假設某兩位數字的和為 sum ,那麼 carry = sum / 10 ,且本位的和應該為 sum / 10 。以此進行迭代,直至兩個連結串列都遍歷完成,要注意的是,迴圈完成之後還要判斷一次 carry 是否還有進位。程式碼實現如下:

public class ListNode {
	int val;
	ListNode next;
	ListNode(int x) { val = x; }
}

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
	ListNode resultHead = new ListNode(0);
	ListNode p1 = l1, p2 = l2, current = resultHead;
	int carry = 0;
	while(p1 != null || p2 != null) {
		int a = p1 !=
null ? p1.val : 0; int b = p2 != null ? p2.val : 0; int sum = a + b + carry; carry = sum / 10; current.next = new ListNode(sum % 10); current = current.next; if(p1 != null) { p1 = p1.next; } if(p2 != null) { p2 = p2.next; } } if(carry > 0) { current.next = new ListNode(carry); } return resultHead.next; }
  • 由於建立了一個新的連結串列,而這個新連結串列最後的長度為 max( len(l1), len(l2) ) + 1 ,也就是說空間複雜度為 O(max( len(l1), len(l2) ))。

  • 迴圈的執行次數為 max( len(l1), len(l2) ) ,所以最後的時間複雜度即為 O(max( len(l1), len(l2) )) 。