1.题目:两个非负整数以逆序形式存储在两个链表,计算他们的和并同样以逆序形式存进链表并返回。
我一开始的思路是把这两条链的数按位数乘10完整提出来,然后相加,再依次取位数对应数字存进链里,返回。
直到他给了我这么一个测试数据,我才明白它用链表传参的目的。
然后我搜了一下long long的取值范围:
-9223372036854775808-9223372036854775807
(即-2^63 - 2^63-1)
以及unsigned long: 0-1844674407370955161
(即0 - 2^64-1)
而这个测试数据起码有30位数!
所以完整提出来相加是不可能的了。
然后到第二个思路:
两个指针同时在对应的相同位置遍历两条链list1和list2,把当前遍历到的数拿出来相加,>=10则抛出进位数cnum=1,结果放到新增空间并尾插到新链,遍历继续。
这只是正常的情况,那么特殊的情况还有什么呢?
( [ ]内代表数字在链表里的顺序)
- 一长一短不进位:[0006]+[003]
(6000+300) - 一长一短进位到最后:[99]+[9999]
(99+9999=10098) - 一长一短进位,但中途结束:[99]+[24912]
(99+21942=22041) - 同长同短,但遍历的最后一组数会进位1:
[5]+[5](5+5=10)
**对于一长一短的情况,我的思路是:
因为遍历条件是p和q同时不为NULL,此时的遍历已经断掉,但仍有p!=NULL或者q!=NULL。
(下面以p!=NULL为例子)
先定义新指针k,记录此时p的位置。
一.若此时进位数cnum为0:
将k直接连接到returnlist的尾端。
二.若此时进位数cnum为1:
则p继续遍历list剩下部分,每遍历一次抛出cnum的值,直到cnum等于0,遍历停止。
在此条件下(cnum为1),若遍历在最后一个数前停止,将k连接到returnlist的尾端;若在最后一个数的位置停止,则新增空间将其值设为1,连接到list1尾部,再将k连接到returnlist的尾端。
**同长同短,遍历最后一组数据进位1:
直接新增空间设置其值为1,连接到新链表尾部。
下面贴代码:
思路1(局限于长整型数据类型范围内):
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
long long x1 = 0, x2 = 0, count=1,ans = 0;
ListNode* p;
p = l1; /*指向链1的第1个节点*/
while (p != NULL) { /*做循环,读取x1的值*/
x1 += (p->val * count);
p = p->next;
count *= 10;
}
count = 1; /*结束count置一*/
p = l2; /*指向链2的第1个节点*/
while (p != NULL) { /*做循环,读取x2的值*/
x2 += (p->val * count);
p = p->next;
count *= 10;
}
ans = x1 + x2;
long long tool = ans, flag = 0;
do { /*整除法获取结果ans的位数*/
tool =tool/10;
flag++;
} while (tool != 0);
ListNode* answer = new ListNode;
answer->next = NULL;
count = 1;
for (int i = 1; i < flag; i++)
count *= 10; /*根据位数建立'取余法'的变量值*/
for (int i = 0; i < flag; i++) { /*将结果头插入链*/
int part =ans / count;
ans = ans - part * count;
p = new ListNode;
p->val = part;
p->next = answer->next;
answer->next = p;
count /= 10;
}
answer=answer->next;
return answer;
}
};
思路一写了好久也想贴一下,原谅我的菜 ╮(╯﹏╰)╭
思路二(正确解法):
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* answer=new ListNode, * p = l1, * q = l2,*k=NULL,*o=NULL;
answer->next = NULL;
ListNode *New, * flag=answer;
int ans = 0,judge=0;
while (p != NULL && q != NULL) { /*从链头到尾 对l1和l2每个对应节点做加法*/
if (judge==1) { /*如果上两个数有进位,则加上1*/
if ((p->val+q->val+judge)>=10) {
ans = (p->val + q->val+judge) % 10;
judge= 1;
}
if ((p->val + q->val+judge) < 10) {
ans = p->val + q->val+judge;
judge = 0;
}
}
else {
if ((p->val + q->val) >= 10) {
ans = (p->val + q->val) % 10;
judge = 1;
}
if ((p->val + q->val) < 10) {
ans = p->val + q->val;
judge = 0;
}
}
New = new ListNode;
New->val = ans;
New->next = flag->next; /*尾插法,flag->next永远是NULL*/
flag->next = New;
flag = flag->next;
p = p->next; q = q->next;/*p,q遍历*/
}
if (p == NULL && q == NULL&&judge==1) {
New = new ListNode;
New->val = 1;
New->next = NULL;
flag->next = New;
}
if (p == NULL&&q!=NULL) { /*一长一短,q还没断*/
k = q;
if (judge == 0)flag->next = k;
if (judge == 1) {
while (q != NULL && judge == 1) {
if ((q->val + judge) >= 10) {
q->val = (q->val + judge) % 10;
judge = 1;
}
else {
q->val = q->val + judge;
judge = 0;
}
o = q;
q = q->next;
}
if (q == NULL && judge == 1) {
New = new ListNode;
New->val = 1;
New->next = NULL;
o->next = New;
}
flag->next = k;
}
}
if (q == NULL && p != NULL) {/*一长一短,p还没断*/
k = p;
if (judge == 0)flag->next = k;
if (judge == 1) {
while (p != NULL && judge == 1) {
if ((p->val + judge) >= 10) {
p->val = (p->val + judge) % 10;
judge = 1;
}
else {
p->val = p->val + judge;
judge = 0;
}
o = p;
p = p->next;
}
if (p == NULL && judge == 1) {
New = new ListNode;
New->val = 1;
New->next = NULL;
o->next = New;
}
flag->next = k;
}
}
answer = answer->next;/*去头(我个人认为去不去都可以)*/
return answer;
}
};
小结:
这个题目的思路对的话,再把每种情况想清楚就OK,运用一些简单的if和else语句,还有单链表的尾插法与头插法。
网上有更优的解法,轻喷。