1.题目
2.分析
思路1:利用双指针,计算出两者长度相差多少
思路2:先逆序链表,从前向后构造新链表
3.代码
思路1:暴力
利用双指针,求解两个链表长度相差多少,而后依次存储每一位,构造新链表
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* p1 = l1, *p2 = l2;
while(p1 && p2){
p1 = p1 -> next;
p2 = p2 -> next;
}
int k1 = 0, k2 = 0;
while(p1){
++k1;
p1 = p1 -> next;
}
while(p2){
++k2;
p2 = p2 -> next;
}
int res[110];
int k = 0;
ListNode* dummy = new ListNode(-1);
ListNode* newhead = dummy;
if(k1 >= k2){ //l1 的 长度较长
p1 = l1, p2 = l2;
while(k1--){
res[k++] = p1 -> val;
p1 = p1 -> next;
}
while(p1 && p2){
res[k++] = p1 -> val + p2 -> val;
p1 = p1 -> next;
p2 = p2 -> next;
}
for(int i = k - 1; i > 0; --i){
res[i-1] += res[i] / 10;
res[i] %= 10;
}
int inithead = res[0] / 10;
res[0] %= 10;
if(inithead){
ListNode* n = new ListNode(inithead);
dummy -> next = n;
dummy = dummy -> next;
}
for(int i = 0; i < k; ++i){
//printf("%d ",res[i]);
ListNode* node = new ListNode(res[i]);
dummy -> next = node;
dummy = dummy -> next;
}
}else{ //l2 长度较长
p1 = l1, p2 = l2;
while(k2--){
res[k++] = p2 -> val;
p2 = p2 -> next;
}
while(p1 && p2){
res[k++] = p1 -> val + p2 -> val;
p1 = p1 -> next, p2 = p2 -> next;
}
for(int i = k -1; i > 0; --i){
res[i-1] += res[i] / 10;
res[i] %= 10;
}
int inithead = res[0] / 10;
res[0] %= 10;
if(inithead){
ListNode* node = new ListNode(inithead);
dummy -> next = node;
dummy = dummy -> next;
}
for(int i = 0; i < k; ++i){
ListNode* node = new ListNode(res[i]);
dummy -> next = node;
dummy = dummy -> next;
}
}
return newhead -> next;
}
};
思路2:逆序相加
反转链表,相加,再反转新链表即可
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
//逆序l1 l2
l1 = reverseList(l1);
l2 = reverseList(l2);
//构建l3
ListNode* dummy = new ListNode(-1);
ListNode* l3 = dummy;
ListNode* p1 = l1, *p2 = l2;
int t = 0; //注意初始化为0 ,否则为随机值
int k = 0;
while(p1 && p2){
t += p1 -> val + p2 -> val;
ListNode* node = new ListNode(t % 10);
dummy -> next = node;
dummy = dummy -> next;
t /= 10;
p1 = p1 -> next, p2 = p2 -> next;
}
while(p1){
t += p1 -> val;
ListNode* node = new ListNode(t % 10);
dummy -> next = node;
dummy = dummy -> next;
t /= 10;
p1 = p1 -> next;
}
while(p2){
t += p2 -> val;
ListNode* node = new ListNode(t % 10);
dummy -> next = node;
dummy = dummy -> next;
t /= 10;
p2 = p2 -> next;
}
if(t){
ListNode* node = new ListNode(t);
dummy -> next = node;
dummy = dummy -> next;
}
dummy -> next = nullptr;
l3 = reverseList(l3->next);
return l3;
}
ListNode* reverseList(ListNode* head){
if(head == nullptr || head -> next == nullptr) return head;
ListNode* newhead = reverseList(head -> next);
head -> next -> next = head; //head -> next 指向的是,head之后逆序链表的尾部
head -> next = nullptr;
return newhead;
}
// void Print(ListNode* head){
// auto t = head;
// while(t){
// printf("%d ",t -> val);
// t = t -> next;
// }
// }
};
思路3:栈 [要加强逆序问题考虑栈的想法]
利用栈的先入后出特性,同时,插入节点时头插,则相当于逆序新链表,得到真正的结果
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack <int> s1,s2;
while(l1){
s1.push(l1 -> val);
l1 = l1 -> next;
}
while(l2){
s2.push(l2 -> val);
l2 = l2 -> next;
}
int t = 0; //进位
ListNode* l3 = new ListNode(-1);
while(!s1.empty() || !s2.empty() || t){ //栈不空 或者 t非零
//栈不空, 则弹出栈顶
int a = s1.empty() ? 0 : s1.top();
int b = s2.empty() ? 0 : s2.top();
if(!s1.empty()) s1.pop();
if(!s2.empty()) s2.pop();
t += a + b; //更新记录
//直接头插,相当于逆序存储
ListNode* node = new ListNode(t % 10);
node -> next = l3 -> next;
l3 -> next = node;
t /= 10; //更新进位
}
return l3 -> next;
}
};
4.总结
递归、链表反转、栈
5.更新日志
2022.10.3
欢迎交流、讨论、指正~
不正确、不理解之处欢迎评论留言~