LeetCode | Add Two Numbers(兩個連結串列相加)
阿新 • • 發佈:2019-02-20
題目:
You are given two linked lists representing two non-negative numbers. 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.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
題意解析:
題目就是將兩個連結串列對應位的數目進行相加,但如果超過十的話,需要進1,跟整數的加法一樣,只是每個結點儲存1位。
題目很簡單,並且看到樣例更會受到誤導。需要先考察連結串列L1和連結串列L2的長度,哪一個比較長。當最後一位相加後再產生進位,也要單獨處理。還有,我們建立連結串列的時候是在表頭插入還是在表尾插入等等。這些方面都要考慮。
方案一:
這個是我的方法,將L2的資料加到L1上,當L2的長度比L1長的話,將多出的結點連結到L1上。(這裡就導致一個問題,當我們最後銷燬兩個連結串列的時候,L2和L1有了公共結點,會導致系統崩潰。需要額外處理,不過我沒有加上這段程式碼,只是設定q的父節點,當L2後續結點連結到L1後,將q的父節點的next指標設為空即可。)最末尾的時候,要單獨處理一下進位。
#include <stdio.h> #include <stdlib.h> typedef struct LNode{ int data; struct LNode *next; }LNode,*LinkList; LinkList InitList(void) { LinkList head = (LinkList)malloc(sizeof(LNode)); if(head == NULL){ printf("Memory allocation failure!\n"); exit(1); } head->next = NULL; return head; } void CreateList(LinkList head,int data) { LinkList p = (LinkList)malloc(sizeof(LNode)); if(!p){ printf("Memory allocation failure!\n"); exit(1); } p->data = data; p->next = head->next; head->next = p; } void AddList(LinkList dest,LinkList src) { LinkList p,q,parent; int carryover = 0; if(!dest || !src){ printf("NULL!"); exit(1); } parent = dest; p = parent->next; q = src->next; while(p && q){ p->data += q->data + carryover; carryover = p->data / 10; p->data %= 10; parent = p; p = parent->next; q = q->next; } if(q) // q->length > p->length parent->next = q; q = parent->next; //將q->length > p->length統一到q->length < p->length上 while(carryover && q){ //如果進位存在,並且q不為空指標的時候,將carryover加到q->data上 q->data += carryover; carryover = q->data / 10; q->data %= 10; parent = q; q = q->next; } if(carryover){ //單獨處理進位 LinkList Q = (LinkList)malloc(sizeof(LNode)); if(!Q) exit(1); Q->data = carryover; Q->next = NULL; parent->next = Q; } } void PrintList(LinkList head) { LinkList p = head->next; while(p){ printf("%d ",p->data); p = p->next; } printf("\n"); } void DestoryList(LinkList head) { LinkList p = head->next,q; head->next = NULL; while(p){ q = p->next; free(p); p = q; } } int main(void) { int n,m,data; LinkList dest,src; dest = InitList(); src = InitList(); printf("input how many numbers of n and m:"); while(scanf("%d %d",&n,&m) == 2){ printf("input the n+m datas:"); for(int i = 0;i < n;++i){ scanf("%d",&data); CreateList(dest,data); } for(int i = 0;i < m;++i){ scanf("%d",&data); CreateList(src,data); } AddList(dest,src); PrintList(dest); printf("input how many numbers of n and m:"); } return 0; }
方案二:
如果這個題目,建立第三方連結串列會更方便,並且將L1->data 、L2->data和carryover三個數相加,分兩次進行,會簡化思路,得到更好的效果。下面這段程式碼摘自網路,很值得學習!
struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) { ListNode* ret = NULL; ListNode** cur = &ret; int carry = 0; int sum = 0; while(l1 != NULL || l2 != NULL) { sum = carry; if(l1 != NULL) { sum += l1->val; l1 = l1->next; } if(l2 != NULL) { sum += l2->val; l2 = l2->next; } carry = sum/10; sum %= 10; *cur = new ListNode(sum); cur = &(*cur)->next; } if(carry > 0) *cur = new ListNode(carry); return ret; } };