链表操作 -- 模拟问题

问题:

        两个链表模拟大整数加法。

    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 }

 

  

转载于:https://www.cnblogs.com/carlsama/p/4126470.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值