《程序员面试金典》--链表相加

题目描述:

《题目1》:

        有两个用链表表示的整数,每个结点包含一个数位。这些数位是反向存放的,也就是个位排在链表的首部。编写函数对这两个整数求和,并用链表形式返回结果。

        给定两个链表ListNode* A,ListNode* B,请返回A+B的结果(ListNode*)。

测试样例:    {1,2,3},{3,2,1}

返回:          {4,4,4}

《题目2》:

如果这些数位是正向存放的,又该如何求解呢?

题目1分析(个位存放在链表头结点):

      如果个位存放在链表头结点的时候,因为我们遍历链表的时候也是从链表头节点开始遍历,正好符合做加法的原则,从各位开始相加,超过10则进1,所以要用一个变量保存每次加法完以后是否有进位,这样递归相加就可以了。

      需要注意的是,递归程序的退出条件是什么,两个链表不一定是一样的长的,所以递归至少也要把最长的链表遍历完,但是如果最后还存在进位,那么还需要递归一次,也就是说递归退出条件是:两个链表都为空且进位为0。

题目1代码实现如下:

  1. struct ListNode {  
  2.     int val;  
  3.     struct ListNode *next;  
  4.     ListNode(int x) : val(x), next(NULL) {}  
  5. };  
  6. class Plus {  
  7. public:  
  8.     //链表首是数据的最低位  
  9.         ListNode* plusAB(ListNode* a, ListNode* b) {  
  10.         return plusAB1(a,b,0);  
  11.         }  
  12.     ListNode* plusAB1(ListNode* a,ListNode* b,int val)  
  13.     {  
  14.         if(a==NULL&&b==NULL&&val==0)  
  15.             return NULL;  
  16.         if(a!=NULL)  
  17.         {  
  18.             val+=a->val;  
  19.             a=a->next;  
  20.         }  
  21.         if(b!=NULL)  
  22.         {  
  23.             val+=b->val;  
  24.             b=b->next;  
  25.         }  
  26.         ListNode *c=new ListNode(val%10);  
  27.         c->next=plusAB1(a,b,val/10);  
  28.         return c;  
  29.     }  
  30. };  

题目2分析(个位存放在链表尾结点):

方法1:      

       如果个位存放在链表尾结点的时候,这个时候必须从链表尾部开始相加,并向前进位,但是我们遍历链表的时候只能从头节点开始遍历,我们仍然可以通过递归实现,只是和题目1递归的前后顺序不一样而已,题目1是先加法再递归,题目2是先递归再加法,也就是每次递归返回的时候需要把进位传过来,这个时候只能通过引用进行进位传递。

      需要注意的是:因为两个链表不是一样的长,我们不能从让两个链表从头开始齐步递归,这样个位无法对齐,所以首先必须求出两个链表的长度,然后让长的链表先和NULL节点递归,等递归到了和短链表齐头并进的时候,再一起递归。

方法2:

       所有递归存在的地方都可以用栈来实现,我们可以用栈来转换上述存储结构,将其转换为和题目1一样从头部遍历的效果。也就是设置两个堆栈,然后从头开始遍历两个链表,将其元素依次放入两个栈中,那么栈顶存放的元素便是个位数,这样和题目一就一样了,可以用尾部递归实现之。

题目2代码实现如下:

  1. class Plus {  
  2. public:  
  3.     //链表首节点是数据的最高位  
  4.     ListNode* plusABL(ListNode* a,ListNode* b)  
  5.     {  
  6.         stack<int> sta,stb;  
  7.         while(a!=NULL)  
  8.         {  
  9.             sta.push(a->val);  
  10.             a=a->next;  
  11.         }  
  12.         while(b!=NULL)  
  13.         {  
  14.             stb.push(b->val);  
  15.             b=b->next;  
  16.         }  
  17.         return plusABL1(sta,stb,0);  
  18.     }  
  19.     ListNode* plusABL1(stack<int> &sta,stack<int> &stb,int val)  
  20.     {  
  21.         if(sta.empty()&&stb.empty()&&val==0)  
  22.             return NULL;  
  23.         if(!sta.empty())  
  24.         {  
  25.             val+=sta.top();  
  26.             sta.pop();  
  27.         }  
  28.         if(!stb.empty())  
  29.         {  
  30.             val+=stb.top();  
  31.             stb.pop();  
  32.         }  
  33.         ListNode *c=new ListNode(val%10);  
  34.         c->next=plusABL1(sta,stb,val/10);  
  35.         return c;  
  36.     }  
  37. };  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值