(一)、單鏈表實現
package com.lin.leetcode.addTwoNumbers; /** * Created by Yaooo on 2019/8/26. */ public class ListNode { int data; ListNode next; ListNode(int data){ this.data = data; } }
package com.lin.leetcode.addTwoNumbers; import java.util.List; /** * Created by Yaooo on 2019/8/25. */ public class SingleLinkedList{ public int size; public ListNode head; // head|next ->null public SingleLinkedList(){ size = 0; head = null; } // head -> a|next ->b|next ->null public void addData(int obj){ ListNode node = new ListNode(obj); if(size == 0){ head = node; node.data= obj; }else{ node.next = head; head = node; node.data = obj; } size++; } // head -> a|next ->b|next ->c|next ->null public boolean deleteData(int value){ if (size == 0){ return false; } ListNode current = head; ListNode previous = head; while(current.data!=value){ if (current.next == null){ return false; }else{ previous = current; current = current.next; } } if(current == head){ head = current.next; size--; }else { previous.next = current.next; size--; } return true; } public void display(){ ListNode node = head; while (node!=null){ if (node.next==null){ System.out.print(node.data ); node = node.next; }else{ System.out.print(node.data + "->"); node = node.next; } } } public static void main(String[] args){ SingleLinkedList list = new SingleLinkedList(); list.addData(1); list.addData(2); list.addData(5); list.deleteData(5); list.display(); } }
實現單鏈表兩數相加:
思路
我們使用變量來跟蹤進位,並從包含最低有效位的表頭開始模擬逐位相加的過程。
圖1,對兩數相加方法的可視化: 342 + 465 = 807342+465=807,每個結點都包含一個數字,並且數字按位逆序存儲。
算法
就像你在紙上計算兩個數字的和那樣,我們首先從最低有效位也就是列表 l1l1 和 l2l2 的表頭開始相加。由於每位數字都應當處於 0 \ldots 90…9 的范圍內,我們計算兩個數字的和時可能會出現 “溢出”。例如,5 + 7 = 125+7=12。在這種情況下,我們會將當前位的數值設置為 22,並將進位 carry = 1carry=1 帶入下一次迭代。進位 carrycarry 必定是 00 或 11,這是因為兩個數字相加(考慮到進位)可能出現的最大和為 9 + 9 + 1 = 199+9+1=19。
偽代碼如下:
- 將當前結點初始化為返回列表的啞結點。
- 將進位 carry 初始化為 0。
- 將 p 和 q 分別初始化為列表 l1 和 l2 的頭部。
- 遍歷列表 l1 和 l2 直至到達它們的尾端。
- 將 x 設為結點 p 的值。如果 pp 已經到達 l1 的末尾,則將其值設置為 0。
- 將 y 設為結點 qq 的值。如果 qq 已經到達 l2 的末尾,則將其值設置為 0。
- 設定 sum=x+y+carry。
- 更新進位的值,carry=sum/10。
- 創建一個數值為(sum mod 10) 的新結點,並將其設置為當前結點的下一個結點,然后將當前結點前進到下一個結點。
- 同時,將 p 和 q 前進到下一個結點。
- 檢查carry=1 是否成立,如果成立,則向返回列表追加一個含有數字 11 的新結點。
- 返回啞結點的下一個結點。
請注意,我們使用啞結點來簡化代碼。如果沒有啞結點,則必須編寫額外的條件語句來初始化表頭的值。
請特別注意以下情況:
測試用例 說明
package com.lin.leetcode.addTwoNumbers; import java.lang.reflect.Array; /** * Created by Yaooo on 2019/8/25. */ public class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode dumpHead = new ListNode(0); ListNode p = l1, q = l2, curr = dumpHead; int carry = 0; while (p != null || q != null) { int x = (p != null) ? p.data : 0; int y = (q != null) ? q.data : 0; int sum = x + y + carry; 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 dumpHead.next; } public static void main(String[] args){ SingleLinkedList l1 = new SingleLinkedList(); l1.addData(1); l1.addData(2); l1.addData(5); SingleLinkedList l2 = new SingleLinkedList(); l2.addData(3); l2.addData(2); l2.addData(7); Solution solution = new Solution(); ListNode l3 = solution.addTwoNumbers(l1.head,l2.head); while (l3!=null){ if(l3.next == null ){ System.out.print(l3.data); l3 = l3.next; }else{ System.out.print(l3.data+"->"); l3 = l3.next; } } } }
復雜度分析
時間復雜度:O(max(m,n)),假設 mm 和 nn 分別表示 l1l1 和 l2l2 的長度,上面的算法最多重復max(m,n) 次。
空間復雜度:O(max(m,n)), 新列表的長度最多為max(m,n)+1。
拓展
如果鏈表中的數字不是按逆序存儲的呢?例如:
(3→4→2)+(4→6→5)=8→0→7
算法引用於鏈接:https://leetcode-cn.com/problems/add-two-numbers/solution/liang-shu-xiang-jia-by-leetcode/