题目描述:
给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
进阶:
如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。
题解:
方法一:因为通常意义的加法是从个位数开始的,所以是从链表的后面往前加的,由于这是两个单链表的相加,在不改变链表的结构前提下,先颠倒两个链表,再进行相加,将结果链表再颠倒。
算法:
- 颠倒链表l1,l2
- 遍历l1,l2将l1和l2指向的结点值和进位值加起来,构成一个新的节点
PS:有三种情况是要创建一个新的节点:1:l1不为空
2:l2不为空
3:进位值不为0
代码:
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *head1=NULL;
while(l1)
{
ListNode *temp=l1->next;
l1->next=head1;
head1=l1;
l1=temp;
}
ListNode *head2=NULL;
while(l2)
{
ListNode *temp=l2->next;
l2->next=head2;
head2=l2;
l2=temp;
}
ListNode *dumpy=new ListNode(-1);
dumpy->next=NULL;
ListNode *head=dumpy;
int carry=0;
while(head1 || head2 || carry){//三种情况,链表加完之后看是否还有进位
int sum = 0;
if (head1){
sum += head1->val;
head1 = head1->next;
}
if (head2){
sum += head2->val;
head2 = head2->next;
}
sum = sum + carry;//各个位置的和
head->next = new ListNode(sum%10);//直接构造链表值
head = head->next;
carry = sum/10;//进位情况
}
ListNode *p=dumpy->next;
ListNode* h=NULL;
while(p)
{
ListNode *temp=p->next;
p->next=h;
h=p;
p=temp;
}
return h;
}
};
方法二:一般逆序处理,都要想到用栈。
算法:
- 将l1和l2分别压入栈s1和s2中
- 然后判断栈s1和s2是否非空,还有进位三种情况
- 初始sum=0;还有一个临时节点初始化为NULL
l1非空:则sum=sum+l1->val;
l2非空:则sum=sum+=l2->val;
进位不为0:sum=sum+carry
- 创建一个新节点(三种情况都会新产生一位,所以要创建一个新节点)new ListNode(sum%10),改变进位carry=sum/10;
- 让新节点指向临时节点,然后让临时节点=当前节点
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
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 carry=0;
ListNode *head=NULL;
while(!s1.empty()||!s2.empty()||carry)
{
int sum=0;
if(!s1.empty())
{
sum+=s1.top();
s1.pop();
}
if(!s2.empty())
{
sum+=s2.top();
s2.pop();
}
sum=(sum+carry);
carry=sum/10;
ListNode *newNode=new ListNode(sum%10);
newNode->next=head;
head=newNode;
}
return head;
}
};