445.兩數相加Ⅱ
445.兩數相加
題目
給你兩個 非空 連結串列來代表兩個非負整數。數字最高位位於連結串列開始位置。它們的每個節點只儲存一位數字。將這兩數相加會返回一個新的連結串列。
你可以假設除了數字 0 之外,這兩個數字都不會以零開頭。
給你兩個 非空 連結串列來代表兩個非負整數。數字最高位位於連結串列開始位置。它們的每個節點只儲存一位數字。將這兩數相加會返回一個新的連結串列。
你可以假設除了數字 0 之外,這兩個數字都不會以零開頭。
示例1:
輸入:l1 = [7,2,4,3], l2 = [5,6,4]
輸出:[7,8,0,7]
示例2:
輸入:l1 = [2,4,3], l2 = [5,6,4] 輸出:[8,0,7]
示例3:
輸入:l1 = [0], l2 = [0]
輸出:[0]
提示:
連結串列的長度範圍為 [1, 100]
0 <= node.val <= 9
輸入資料保證連結串列代表的數字無前導 0
進階:如果輸入連結串列不能翻轉該如何解決?
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/add-two-numbers-ii
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
題解1
第一個問題就是如何對齊,連結串列長度是不一樣的,誰與誰相加?
長度不一樣,我們可以通過在短連結串列前面新增0節點,是兩個連結串列長度一樣,那麼頭節點對頭節點,尾節點對尾節點就對齊了。
ListNode tail1 =l1; ListNode tail2 =l2; //都走到最後一個節點就停止新增 while(tail1.next==null && tail2.next==null){ if(tail1.next == null){ //說明到尾了但是還在迴圈裡說明tail2還沒有到尾 ListNode tmp = new ListNode(0); tmp.next = l1; l1 = tmp; } if(tail2.next == null){ ListNode tmp = new ListNode(0); tmp.next = l2; l2 = tmp; } tail1 = tail1.next ==null ? tail1 : tail1.next; tail2 = tail1.next ==null ? tail2 : tail2.next; }
處理完對齊的問題後,如何處理相加?相加是從低位開始相加,如果有進位需要向前一位傳遞。
而連結串列的遍歷順序一般是從左到右,現在我們需要從右到左,那麼可以翻轉連結串列,加完之後再翻轉回來。
//翻轉連結串列
ListNode reverseList(ListNode head){
ListNode pre=null;
ListNode tmp;
while(head!=null){
tmp = head.next; //防止斷鏈,記錄下要反轉的節點的後一個節點
head.next = pre; //開始反轉指向前一個
pre = head;
head = tmp;
}
return pre; //返回新的頭節點
}
開始計算,這裡的指標有點多,整理一下
tail1 指向 l1 的最後一個節點,也就是翻轉後的頭節點,l1指向翻轉後的最後一個節點
tail2 指向 l2 的最後一個節點,也就是翻轉後的頭節點,l2指向翻轉後的最後一個節點
ListNode pre = reverseList(l1);
reverseList(l2);
int flag = 0 ;//表示十位
while(tail1!=null){//長度是一樣的
tail1.val = (tail1.val + tail2.val+flag)%10; //取個位數
flag = (tail1.val + tail2.val+flag)/10; //取十位數
tail1 = tail.next();
}
if(flag!=0) 新增一個節點
reverseList(pre);
return l1;
程式碼
現在整理一下所有思路,發現如果先翻轉連結串列,那可以不用補節點了,翻轉之後,都從頭開始個位數自然會對齊。如果遇見null就算0。
新連結串列採用頭插法就不用再翻轉一次了。
l1 = reverseList(l1); //指向新的頭節點
l2 = reverseList(l2); //翻轉連結串列
int flag = 0 ;//表示十位
int val1=0,val2=0;
ListNode dummy = new ListNode(); //新連結串列的頭節點
ListNode tmp;
ListNode newHead;
//做加法,不同時為空,同時為空說明已經加完了
while(!(l1==null && l2==null)){
val1 = l1 == null? 0 : l1.val;
val2 = l2 == null? 0 : l2.val;
tmp = dummy.next;
newHead = new ListNode((val1 + val2+flag)%10); //取個位數
dummy.next = newHead;
newHead.next = tmp;
flag = (val1 + val2+flag)/10; //取10位數
//遍歷下一個節點
l1 = l1 == null? null:l1.next;
l2 = l2 == null? null: l2.next;
}
//flag如果有值,說明進位只有還需要新增一個節點
if(flag!=0){
newHead = new ListNode(flag);
tmp = dummy.next;
dummy.next = newHead;
newHead.next = tmp;
}
return dummy.next;
//翻轉連結串列
ListNode reverseList(ListNode head){
ListNode pre=null;
ListNode tmp;
while(head!=null){
tmp = head.next; //防止斷鏈,記錄下要反轉的節點的後一個節點
head.next = pre; //開始反轉指向前一個
pre = head;
head = tmp;
}
return pre; //返回新的頭節點
}
題解2
逆序處理:還可以通過棧
總結
逆序遍歷連結串列
- 翻轉連結串列
- 棧