上一篇博客:LeetCode 1.兩數之和(數組、哈希表)
寫在前面:大家好!我是
ACfun
,我的暱稱來自兩個單詞Accepted
和fun
。我是一個熱愛ACM的蒟蒻。最近萌生了刷LeetCode的想法,所以我打算按照題號從LeetCode第一個題目開始做起,攻陷LeetCode。如果博客中有不足或者的錯誤的地方歡迎在評論區或者私信我指正,感謝大家的不吝賜教。我的唯一博客更新地址是:https://ac-fun.blog.csdn.net/。非常感謝大家的支持。一起加油,衝鴨!
用知識改變命運,用知識成就未來!加油 (ง •̀o•́)ง (ง •̀o•́)ง
原題鏈接:LeetCode 2. 兩數相加
題目信息
題目描述
給出兩個 非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照 逆序 的方式存儲的,並且它們的每個節點只能存儲 一位 數字。
如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。
您可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。
示例
輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807
解題思路
剛開始看題目的時候看到了需要使用鏈表感覺這個題目應該很難,其實這是個錯覺。這個題目本質上就是我們平常做加法的方法,從個位開始加超過10就進位,然後依次將個位十位百位……相加最後得出結果。我們也可以通過數組來實現,但是題目有限制,讓我們使用鏈表來做。
我覺得這還是一個高精度問題,高精度問題在之前的博客 藍橋杯練習系統 基礎練習(vip試題):BASIC-30 階乘計算 中提到過。大家感興趣可以去看一看,這裏就不贅述了。
首先申請一個頭結點,然後再申請一個結點sum,sum結點指向頭結點。定義一個carry變量用來進位,初始化爲0,然後就開始遍歷 l1 和 l2 兩個單鏈表,只要這兩個單鏈表不爲空或者carry不爲0就進行相加操作。分別判斷當前結點是否爲空,如果不爲空說明第一個數或者第二個數該數位上還有數值,那麼就將其加到carry上。然後申請一個新的結點使其指向sum的下一個結點,數值爲carry % 10,如果carry小於10那麼carry還是原數值,如果carry大於10,那麼就會只將個位保存在該結點上。然後使carry / 10,如果carry大於10那麼只會保留十位上的數字,即完成了進位操作,不斷進行這個操作,直到 l1 爲空 l2 爲空並且 carry 爲 0。最後返回頭結點的下一個結點,即結果鏈表的真正的地址。
時間複雜度
假設鏈表 l1 的長度爲m,l2 的長度爲n,max表示兩者之間的最大值,則該方法的時間複雜度爲:O(max(m,n))。
解題代碼
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
//auto dummy = new ListNode(-1),sum = dummy; auto變量可以在聲明變量的時候根據變量初始值的類型自動爲此變量選擇匹配的類型
ListNode *head = new ListNode(),*sum = head; //申請一個頭結點head,並使sum指向head。
int carry = 0; //carry 用來進位
while(l1 || l2 || carry){
if(l1) carry += l1->val, l1 = l1->next;
if(l2) carry += l2->val, l2 = l2->next;
sum->next = new ListNode(carry % 10);
sum = sum->next; //更新頭結點
carry /= 10;
}
return head->next;
}
};
提交情況
未完待續,持續更新中……