题目描述:
《题目1》:
有两个用链表表示的整数,每个结点包含一个数位。这些数位是反向存放的,也就是个位排在链表的首部。编写函数对这两个整数求和,并用链表形式返回结果。
给定两个链表ListNode* A,ListNode* B,请返回A+B的结果(ListNode*)。
测试样例: {1,2,3},{3,2,1}返回: {4,4,4}
《题目2》:
如果这些数位是正向存放的,又该如何求解呢?
题目1分析(个位存放在链表头结点):
如果个位存放在链表头结点的时候,因为我们遍历链表的时候也是从链表头节点开始遍历,正好符合做加法的原则,从各位开始相加,超过10则进1,所以要用一个变量保存每次加法完以后是否有进位,这样递归相加就可以了。
需要注意的是,递归程序的退出条件是什么,两个链表不一定是一样的长的,所以递归至少也要把最长的链表遍历完,但是如果最后还存在进位,那么还需要递归一次,也就是说递归退出条件是:两个链表都为空且进位为0。
题目1代码实现如下:
- struct ListNode {
- int val;
- struct ListNode *next;
- ListNode(int x) : val(x), next(NULL) {}
- };
- class Plus {
- public:
- //链表首是数据的最低位
- ListNode* plusAB(ListNode* a, ListNode* b) {
- return plusAB1(a,b,0);
- }
- ListNode* plusAB1(ListNode* a,ListNode* b,int val)
- {
- if(a==NULL&&b==NULL&&val==0)
- return NULL;
- if(a!=NULL)
- {
- val+=a->val;
- a=a->next;
- }
- if(b!=NULL)
- {
- val+=b->val;
- b=b->next;
- }
- ListNode *c=new ListNode(val%10);
- c->next=plusAB1(a,b,val/10);
- return c;
- }
- };
题目2分析(个位存放在链表尾结点):
方法1:
如果个位存放在链表尾结点的时候,这个时候必须从链表尾部开始相加,并向前进位,但是我们遍历链表的时候只能从头节点开始遍历,我们仍然可以通过递归实现,只是和题目1递归的前后顺序不一样而已,题目1是先加法再递归,题目2是先递归再加法,也就是每次递归返回的时候需要把进位传过来,这个时候只能通过引用进行进位传递。
需要注意的是:因为两个链表不是一样的长,我们不能从让两个链表从头开始齐步递归,这样个位无法对齐,所以首先必须求出两个链表的长度,然后让长的链表先和NULL节点递归,等递归到了和短链表齐头并进的时候,再一起递归。
方法2:
所有递归存在的地方都可以用栈来实现,我们可以用栈来转换上述存储结构,将其转换为和题目1一样从头部遍历的效果。也就是设置两个堆栈,然后从头开始遍历两个链表,将其元素依次放入两个栈中,那么栈顶存放的元素便是个位数,这样和题目一就一样了,可以用尾部递归实现之。
题目2代码实现如下:
- class Plus {
- public:
- //链表首节点是数据的最高位
- ListNode* plusABL(ListNode* a,ListNode* b)
- {
- stack<int> sta,stb;
- while(a!=NULL)
- {
- sta.push(a->val);
- a=a->next;
- }
- while(b!=NULL)
- {
- stb.push(b->val);
- b=b->next;
- }
- return plusABL1(sta,stb,0);
- }
- ListNode* plusABL1(stack<int> &sta,stack<int> &stb,int val)
- {
- if(sta.empty()&&stb.empty()&&val==0)
- return NULL;
- if(!sta.empty())
- {
- val+=sta.top();
- sta.pop();
- }
- if(!stb.empty())
- {
- val+=stb.top();
- stb.pop();
- }
- ListNode *c=new ListNode(val%10);
- c->next=plusABL1(sta,stb,val/10);
- return c;
- }
- };