【leetcode】【medium】445. Add Two Numbers II

230 篇文章 0 订阅

445. Add Two Numbers II

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

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

 

题目不允许反转输入数据,因此直接不考虑这种方法。

法一:辅助空间

我使用的是vector,但其他答案推荐使用stack。

stack符合反转的思想确实更好。

这个方法空间复杂度较高。

注意边界例子:最后要判断是否因进位而生成的新的位。

Input:
[5]
[5]
Output:
[0]
Expected:
[1,0]
/**
 * 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) {
        vector<int> v1, v2;
        while(l1!=NULL){
            v1.push_back(l1->val);
            l1 = l1->next;
        }
        while(l2!=NULL){
            v2.push_back(l2->val);
            l2 = l2->next;
        }
        int flag = 0, i = 0, len1 = v1.size()-1, len2 = v2.size()-1;
        ListNode *head = new ListNode(0);
        while(len1>=0 && len2>=0){
            int tmp = v1[len1] + v2[len2] + flag;
            flag = tmp / 10;
            ListNode *node = new ListNode(tmp%10);
            node->next = head->next;
            head->next = node;
            --len1;
            --len2;
        }
        while(len1>=0){
            int tmp = v1[len1] + flag;
            flag = tmp / 10;
            ListNode *node = new ListNode(tmp%10);
            node->next = head->next;
            head->next = node;
            --len1;
        }
        while(len2>=0){
            int tmp = v2[len2] + flag;
            flag = tmp / 10;
            ListNode *node = new ListNode(tmp%10);
            node->next = head->next;
            head->next = node;
            --len2;
        }
        if(flag){
            ListNode *node = new ListNode(flag);
            node->next = head->next;
            head->next = node;
        }
        return head->next;
    }
};

法二:先取长度,两次遍历

第一次遍历取两个链的长度,第二次遍历从相应的位上开始做加法,需要一个指针为了进位操作而记录从此处往前第一个<9的节点(连续进位)。

此法可以直接在较长的链上进行修改,直接返回被修改的链。时间复杂度和空间复杂度都较低。

一个代码实现的小tric:如何实现修改较长的链。if和else写两段重复代码?不!只需交换长短链的名字,保证名字就能代表长短。

注意:此法不需要进位标识flag,因为每次进位都是在本次遍历完成。而前方法需要flag是因为,每次进位遍历下个节点时完成。

/**
 * 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) {
        int len1 = 0, len2 = 0;
        ListNode *cur1 = l1, *cur2 = l2;
        while(cur1!=NULL){
            ++len1;
            cur1 = cur1->next;
        }
        while(cur2!=NULL){
            ++len2;
            cur2 = cur2->next;
        } 
        if(len1<len2){
            int ltmp = len1;
            len1 = len2;
            len2 = ltmp;
            ListNode *ntmp = l1;
            l1 = l2;
            l2 = ntmp;
        }
        ListNode *head = new ListNode(0);
        head->next = l1;
        ListNode *less9 = head;
        cur1 = l1, cur2 = l2;
        while(len1>len2){
            if(cur1->val < 9) less9 = cur1;
            cur1 = cur1->next;
            --len1;
        }
        while(len1>0){
            int tmp = cur1->val + cur2->val;
            cur1->val = tmp % 10;
            if(tmp>9){
                while(less9!=cur1){
                    less9->val = (less9->val + 1) % 10;
                    less9 = less9->next;
                }
            }else if(cur1->val < 9) {
                less9 = cur1;
            }
            cur1 = cur1->next;
            cur2 = cur2->next;
            --len1;
        }
        return (head->val == 0)?head->next:head;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值