LeetCode445.Add Two Numbers II题解

1. 题目描述

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.

2. Follow Up

What if you cannot modify the input lists? In other words, reversing the lists is not allowed.

3. 样例
Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 8 -> 0 -> 7
4. 分析

这道题表面上看起来很好理解:即给出了A、B两个链表,我们需要做的事情是将两个链表的对应节点元素相加,得到一个新的链表。但是笔者在做这道题整整花了3个小时!因为最开始努力全部用链表来解,失败了,最后不得不转向熟悉的vector。
分析一下:由于给出的两个链表相加,我们的计算方式都是从低位向高位相加计算的,那么找到两个链表的最低位就成了做这道题的关键步骤:给定的是单向链表,我们没办法很容易的从链表尾开始遍历提取节点存储的数,那么将链表逆置成为了解题思路。虽然题目中follow up提出不要逆置原链表,于是我们用vector将原链表的数值存储起来算作打擦边球吧。
我们用两个vector得到了原来的逆向存储的链表,接下来的事情就容易很多了,每一位对应相加,注意考虑进位的问题,因此要有模10得到这一位的最终数值以及相似的方法求取每一位的进位。需要格外注意的是边界问题的处理

Example1:
Input: (5) + (5)
Output: (1 -> 0)而非(0)
Example2:
Input: (1) + (9 -> 9)
Output: (1 - > 0 -> 0)而非(10 -> 0)
5. 源码(vector版本通过)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

class Solution {
public:
        vector<int> getList(ListNode* h) {
        vector<int> L;
        int value;
        while(h) {
            value = h->val;
            L.push_back(value);
            h = h->next;
        }
        return L;
    }
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *l3 = NULL;
        vector<int> v1 = getList(l1);
        vector<int> v2 = getList(l2);
        reverse(v1.begin(), v1.end());
        reverse(v2.begin(), v2.end());
        vector<int> v3;
        int adds = 0;
        int temp = 0;
        if (v1.size() >= v2.size()) {
            while(v2.size()) {
                temp = (adds + v1.front() + v2.front()) % 10;
                adds = (adds + v1.front() + v2.front()) / 10;
                v3.push_back(temp);
                v1.erase(v1.begin()+0);
                v2.erase(v2.begin()+0);
            }
            while(v1.size()) {
                temp = (adds + v1.front()) % 10;
                adds = (adds + v1.front()) / 10;
                v3.push_back(temp);
                v1.erase(v1.begin()+0);
            }
            if (adds != 0) {
                v3.push_back(adds);
            }
        }
        else {
            while(v1.size()) {
                temp = (adds + v1.front() + v2.front()) % 10;
                adds = (adds + v1.front() + v2.front()) / 10;
                v3.push_back(temp);
                v1.erase(v1.begin()+0);
                v2.erase(v2.begin()+0);
            }
            while(v2.size()) {
                temp = (adds + v2.front()) % 10;
                adds = (adds + v2.front()) / 10;
                v3.push_back(temp);
                v2.erase(v2.begin()+0);
            }
            if (adds != 0) {
                v3.push_back(adds);
            }
        }
        ListNode *add = NULL;
        ListNode *curr = (ListNode*)malloc(sizeof(ListNode));
        curr->next = NULL;
        while(v3.size()) {
            add = (ListNode*)malloc(sizeof(ListNode));
            add->val = v3.front();
            v3.erase(v3.begin()+0);
            add->next = curr->next;
            curr->next = add;
        }
        l3 = curr->next;
        return l3;
    }
};
6. 链表版本(未通过)

这两种算法的基本思路是一样的,都是先求出原链表的逆向链表,然后建立新链表,对应项相加。只不过该版本可以直接利用头插法和尾插法去建立链表,但是好久没写代码了,发现自己链表的基本功都忘了差不多了,写的代码反复不过,这是GG。注意啊,以下是错的!!!!

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void Reverse(ListNode *&h, ListNode *a, int &length) {
        ListNode* r;
        ListNode* s;
        ListNode* p;
        p = a;
        h = (ListNode*)malloc(sizeof(ListNode));
        h->next = NULL;
        r = h;
        while(p) {
            s = (ListNode*)malloc(sizeof(ListNode*));
            s->val = p->val;
            s->next = r->next;
            r->next = s;
            p = p->next;
            length++;
        }
    }
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *r1, *r2;
        ListNode *result = NULL;
        ListNode *curr = (ListNode*)malloc(sizeof(ListNode));
        curr->next = NULL;
        int length1 = 0, length2 = 0;
        Reverse(r1, l1, length1);
        Reverse(r2, l2, length2);
        r1 = r1->next;
        r2 = r2->next;
        ListNode *add;
        int adds = 0;
        int temp = 0;
        if (length1 >= length2) {
            while(r2) {
                temp = adds;
                temp += (r1->val + r2->val)%10;
                adds = (r1->val + r2->val) / 10;
                add = (ListNode*)malloc(sizeof(ListNode));
                add->val = temp;
                add->next = curr->next;
                curr->next = add;
                r1 = r1->next;
                r2 = r2->next;
            }
            while(r1) {
                temp = adds;
                temp += r1->val % 10;
                adds = r1->val / 10;
                add = (ListNode*)malloc(sizeof(ListNode));
                add->val = temp;
                add->next = curr->next;
                curr->next = add;
                r1 = r1->next;
            }
            result = curr->next;
        }
        else {
            while(r1) {
                temp = adds;
                temp += (r1->val + r2->val)%10;
                adds = (r1->val + r2->val) / 10;
                add = (ListNode*)malloc(sizeof(ListNode));
                add->val = temp;
                add->next = curr->next;
                curr->next = add;
                r1 = r1->next;
                r2 = r2->next;
            }
            while(r2) {
                temp = adds;
                temp += r2->val % 10;
                adds = r2->val / 10;
                add = (ListNode*)malloc(sizeof(ListNode));
                add->val = temp;
                add->next = curr->next;
                curr->next = add;
                r2 = r2->next;
            }
            result = curr->next;
        }
        return result;
    }

};
7. 心得

审题仍然很重要,边界考虑也很重要,否则会卡在很多边界的测试样例上面。学会转化思想,链表写法实在搞不定还是老老实实换成自己熟悉的vector吧,但这方面的基本功要复习了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值