原题目
You are given two non-empty linked lists representing two non-negative
integers. The most significant digit comes first and each of their
nodes contain a single digit. Add the two numbers and return it as a
linked list.You may assume the two numbers do not contain any leading zero, except
the number 0 itself.Follow up: What if you cannot modify the input lists? In other words,
reversing the lists is not allowed.Example: Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 8 -> 0
-> 7
中文大意
给定两个非空链表,其中链表头部元素代表最高位,尾部代表最低位,计算出这两个链表作为两个十进制数相加的结果,如 (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) = (7 -> 8 -> 0 -> 7),另外,这道题能否通过不改变输入链表的结构(不将链表逆置)得到?
题解1:通过链表逆置实现
class Solution {
public:
ListNode* reverseList(ListNode* head)
{
if(head==NULL) return head;
ListNode *tail = head;
while(tail->next!=NULL)
tail = tail->next;
ListNode* curr = head;
while(curr!=tail)
{
ListNode* currNext = curr->next;
curr->next = tail->next;
tail->next = curr;
curr = currNext;
}
return tail;
}
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
ListNode* dummy = new ListNode(-1); //创建结果的链表头部
// 先将链表逆置
ListNode* l1_reverse = reverseList(l1);
ListNode* l2_reverse = reverseList(l2);
int carry = 0; //处理进位
while(l1_reverse!=NULL || l2_reverse!=NULL)
{
//处理两个链表不等长,遍历完其中的一个链表的情况
if(l1_reverse==NULL)
{
ListNode* newNode = new ListNode((l2_reverse->val + carry)%10);
carry = (l2_reverse->val + carry)/10;
newNode->next = dummy->next;
dummy->next = newNode;
l2_reverse = l2_reverse->next;
}
else if(l2_reverse ==NULL)
{
ListNode* newNode = new ListNode((l1_reverse->val + carry)%10);
carry = (l1_reverse->val + carry)/10;
newNode->next = dummy->next;
dummy->next = newNode;
l1_reverse = l1_reverse->next;
}
//常规情况
else
{
ListNode* newNode = new ListNode((l1_reverse->val+ l2_reverse->val + carry)%10);
carry = (l1_reverse->val+ l2_reverse->val + carry)/10;
newNode->next = dummy->next;
dummy->next = newNode;
l1_reverse = l1_reverse->next;
l2_reverse = l2_reverse->next;
}
}
if(carry) //如果最高位相加的结果还产生进位,这里需要加上
{
ListNode* newNode = new ListNode(carry);
newNode->next = dummy->next;
dummy->next = newNode;
}
return dummy->next;
}
};
题解1分析
这道题实际上就是模拟两个数的竖式计算,关键是对链表的遍历以及对进位的处理,进位需要用一个额外的变量来存储,等于上一次进位加上当前位的两个加数除10取整。每一位相加的结果都要插入到新的链表的头部,从而避免最后还要对链表进行逆置
题解2:通过栈的实现
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack<int> s1,s2;
//将两个链表中的数分别压到两个栈中
while(l1!=NULL){
s1.push(l1->val);
l1 = l1->next;
}
while(l2!=NULL){
s2.push(l2->val);
l2 = l2->next;
}
ListNode *dummy = new ListNode(-1);
int carry = 0;
while(!s1.empty()||!s2.empty()){
int sum = carry;
if(!s1.empty()) {
sum += s1.top();
s1.pop();
}
if(!s2.empty())
{
sum += s2.top();
s2.pop();
}
ListNode *newDigit = new ListNode(sum%10);
carry = sum/10;
//从头插入
newDigit->next = dummy->next;
dummy->next=newDigit;
}
if(carry)
{
ListNode *newDigit = new ListNode(carry);
newDigit->next = dummy->next;
dummy->next = newDigit;
}
return dummy->next;
}
};
题解2分析
实际上这道题的解题思路是完全一样的,没有对链表本身进行逆置,只不过是对栈而不是链表进行操作,但空间复杂度比之前的要大(O(n)),同样需要注意两点:1. 进位的处理;2. 每次加法的结果插入到头部