Problems:
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.
Example:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
題目是給定兩個鏈表,代表兩個非負整數。整數上的數字逆序存儲,每一個節點包括一個數字,使這兩個整數相加,然後用鏈表返回。
思路:
-
實際上就是一個設計一個類似加法器的東西,用鏈表的數據結構來實現。
-
加法器的基本思路要了解,進位帶着走。
-
需要考慮兩個鏈表長度不一致的情況
- len<min(len1,len2),公共部分的加法
- 當遍歷完短鏈表時,注意加法的加數減少一項
- 全都遍歷之後,若有進位,最高位記得新開結點去存放
C語言代碼:
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
struct ListNode* tmp1;
struct ListNode* tmp2;
struct ListNode* tmp3; //鏈表結點索引
struct ListNode* l3 = NULL;//一開始第三個鏈表爲空,l3鏈表頭指針
int carry=0;
if(l1==NULL||l2==NULL)//有鏈表爲空的話直接返回
{
return (l1==NULL?l2:l1);
}
tmp1=l1; //索引
tmp2=l2;
tmp3=l3;
while(tmp1!=NULL&&tmp2!=NULL)//處理公共部分
{
struct ListNode* newnode= (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = (tmp1->val + tmp2->val + carry)%10;
newnode->next = NULL;
carry = (tmp1->val + tmp2->val + carry)/10;
if(l3==NULL)//如果開始鏈表爲空,那麼就填充值
{
l3 = tmp3 = newnode;
}
else//如果不空,直接將newnode接在後面
{
tmp3->next = newnode;
tmp3 = tmp3->next;// tmp3始終指向鏈表末尾
}
tmp1 = tmp1->next;
tmp2 = tmp2->next;
}
if(tmp1==NULL)//如果第一個鏈表遍歷完了
{
while(tmp2!=NULL)
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = (carry + tmp2->val)%10;
newnode->next = NULL;
carry = (carry + tmp2->val)/10;
tmp3->next = newnode;
tmp3 = tmp3->next; // tmp3移到裏l3鏈表末尾
tmp2 = tmp2->next;
}
if(carry!=0) // 最高位還有進位
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = (carry)%10;
newnode->next = NULL;
tmp3->next = newnode;
newnode->next = NULL;
}
}
if(tmp2==NULL)//如果第一個鏈表遍歷完了
{
while(tmp1!=NULL)
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = (carry + tmp1->val)%10;
newnode->next = NULL;
carry = (carry + tmp1->val)/10;
tmp3->next = newnode;
tmp3 = tmp3->next; // tmp3移到裏l3鏈表末尾
tmp1 = tmp1->next;
}
if(carry!=0) // 最高位還有進位
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = (carry)%10;
newnode->next = NULL;
tmp3->next = newnode;
}
}
return l3;
}
注意點
- 如何新建結點?
- 結構體指針變量和結構體變量對於成員的引用方式?( . 和 -> )
- 加法器設計,
value = (carry + add1 + add2 )% 10; carry = (carry + add1 + add2 ) /10
- 關於新建鏈表的問題:
- 新建鏈表的標準做法是新建頭結點分配結點空間,置next爲NULL,然後再用頭插法、尾插法來構建鏈表。但是做題目時候注意返回的指針是頭結點後一個有值的結點。
- 上面這種方法沒有標準頭結點,鏈表的第一個結點即有值,所以需要多加一個if判斷該結點是否爲開始結點。