链表操作 -- 模拟问题
问题:
两个链表模拟大整数加法。
1-》2-》3 + 4-》5 = 1-》6-》8
解答:
1)使用递归实现。
比直接使用迭代实现更好。
加法需要从最低位开始,在使用递归实现时,会先递归到最底层(len==1)的情况,然后依次返回到上一层并伴随返回进位数。这样就比直接的迭代实现节省了每次定位同层节点的时间。
1 int length(const Node* head) 2 { 3 int length = 0; 4 while(head != NULL) 5 { 6 length++; 7 head = head->next; 8 } 9 10 return length; 11 } 12 13 //headA指的链表长度不小于headB 14 int __add(Node* headA, int lenA, Node* headB, int lenB) 15 { 16 int sum = -1; 17 if(lenA == 1) 18 sum = headA->data + headB->data; 19 else if(lenA > lenB) 20 sum = headA->data + __add(headA->next, --lenA, headB, lenB); 21 else//现在只剩下lenA == lenA的情况 22 sum = headA->data + headB->data + __add(headA->next, --lenA, headB->next, --lenB); 23 24 headA->data = sum % 10; 25 return sum / 10; 26 } 27 28 Node* add(Node* listA,Node* listB) 29 { 30 if(listA == NULL) 31 return listB; 32 if(listB == NULL) 33 return listA; 34 35 int lenA = length(listA); 36 int lenB = length(listB); 37 Node* longer = listA; 38 Node* shorter = listB; 39 if(lenA <lenB) 40 { 41 longer = listB; 42 shorter = listA; 43 } 44 45 int carry = __add(longer, lenA, shorter, lenB); 46 if(carry != 0) 47 { 48 Node* head = new Node(carry); 49 head->next = longer; 50 longer = head; 51 } 52 53 return longer; 54 }
2)迭代实现
直接的迭代实现较为浪费时间,在由尾向头坐加法时,每次需要遍历过程来获取某一个位置的节点,花费O(n)的时间;
可以使用堆栈,讲两个链表的同层节点压入依次压入堆栈。然后再依次弹出、计算。这个过程其实就和函数递归调用一样的了。在此不表。
3)逆转实现【贺斌启发下完成】
如果有链表1-》2-》3-》NULL 和 链表4-》5-》NULL,此时我们的相加操作代表123 + 45。
如果我们将链表修改为3-》2-》1-》NULL和5-》4-》NULL,这样就可以从左向右的相加了!之后再将搜求的链表反转就可以了。
反转操作,我们之前已经讲解过了,可以达到O(n)的时间复杂度,而相加操作耗时O(n)。总的时间复杂度为O(n)。
问题:
两个链表模拟大整数加法。
1-》2-》3 + 4-》5 = 5-》7-》3
题目来自:Leetcode -- Add Two Numbers
解答:
1 ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) 2 { 3 ListNode newHead(0); 4 ListNode* p = &newHead; 5 6 int carry = 0; 7 while(l1 || l2 || carry) 8 { 9 int n1 = (l1 == NULL)?0:l1->val; 10 int n2 = (l2 == NULL)?0:l2->val; 11 12 //这里我们产生新的节点来存储和 13 //而非直接使用p来存储 14 //直接使用p来存储的时候,还需要传递prev指针来指向p。 15 p->next = new ListNode((n1 + n2 + carry)%10); 16 p = p->next; 17 18 carry = (n1 + n2 + carry)/10; 19 20 if(l1) 21 l1 = l1->next; 22 23 if(l2) 24 l2 = l2->next; 25 } 26 return newHead.next; 27 }