【LeetCode-链表】两数相加

题目描述

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

题目链接:https://leetcode-cn.com/problems/add-two-numbers/

思路

用链表来模拟人做加法,注意每一位的进位,以及最后是否有进位。最后如果有进位的话,则需要多加一个节点。代码如下:

/**
 * 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) {
        if(l1==nullptr || l2==nullptr){
            return nullptr;
        }

        int carry = 0;  // 当前的进位
        ListNode* head = new ListNode(0);   // 新链表的链表头
        ListNode* curNode = head;
        while(l1!=nullptr && l2!=nullptr){
            int s = l1->val+l2->val+carry;
            ListNode* node = new ListNode(s%10);
            carry = s/10;
            curNode->next = node;
            curNode = node;
            l1 = l1->next;
            l2 = l2->next;
        }
        if(l1==nullptr && l2!=nullptr){ //说明l1比较短,将l2剩余的部分加入到新链表当中
            while(l2!=nullptr){
                int s = l2->val+carry;
                ListNode* node = new ListNode(s%10);
                carry = s/10;
                curNode->next = node;
                curNode = node;
                l2 = l2->next;
            }
        }
        if(l1!=nullptr && l2==nullptr){ //说明l2比较短,将l1剩余的部分加入到新链表当中
            while(l1!=nullptr){
                int s = l1->val+carry;
                ListNode* node = new ListNode(s%10);
                carry = s/10;
                curNode->next = node;
                curNode = node;
                l1 = l1->next;
            }
        }
        if(l1==nullptr && l2==nullptr){ // 看最后有没有进位比如[1]+[9],有的话加上
            if(carry!=0){   //有进位
                ListNode* node = new ListNode(carry);
                curNode->next = node;
            }
        }
        return head->next;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
    链表所占的额外存储空间与输入的数据规模线性相关。

更简洁的代码
上面的代码可以写得更简洁,如下:

/**
 * 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) {
        if(l1==nullptr || l2==nullptr){
            return nullptr;
        }


        int carry = 0;  // 当前的进位
        ListNode* head = new ListNode(0);
        ListNode* curNode = head;
        while(l1!=nullptr || l2!=nullptr){
            int x = l1==nullptr? 0:l1->val;
            int y = l2==nullptr? 0:l2->val;
            int s = x+y+carry;
            ListNode* node = new ListNode(s%10);
            curNode->next = node;
            curNode = node;
            carry = s/10;
            if(l1!=nullptr) l1 = l1->next;
            if(l2!=nullptr) l2 = l2->next;
        }
        if(carry!=0){
            ListNode* node = new ListNode(carry);
            curNode->next = node;
        }
        return head->next;
    }
};

两种写法的时间空间复杂度是一样的。

总结

在模拟整数相加的时候,假设当前两个数相加为s,则s/10表示进位,s%10表示当前加的结果。

原文地址:https://www.cnblogs.com/flix/p/12671988.html