zoukankan      html  css  js  c++  java
  • Leetcode 002. 两数相加

    1.题目描述

    给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

    如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

    您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

    示例:

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

    2.我的错误版本

    2.1 解题思路

    题中链表顺序正好是低位到高位,先低位相加,有进位保持,下一位计算加上进位,直到最高位相加,如果有进位,生成新的结点保存。

    2.2 我的错误代码

    有时候,从错误中才能学到真知识。

    现在刷题,很容易到网上找到各种答案,因此,初学者往往因为无法忍受一遍又一遍的调试,而放弃独立思考,选择取拷贝别人的代码,以理解别人的代码代替了自己刷题的那个拔高的训练过程,这实在是很可惜的,刷题的效果会大打折扣。

    我的错误:

    1. 应当创建新的链表来保存结果,保留原链表。因为传入原链表L1和L2可能还需要用到,不能轻易更改;
    2. 解题思路不对:
      • a.用了繁琐的思路
      • b.用了繁琐的思路但没有列举全所有可能的情况:(1)两个链表一样长;(2)L1比L2长;(3)L2比L1长;(4)两个链表均为单结点,如5和5,这个测试用例反复修改,过不了,最后发现要换思路才能过。(方法不对,努力白费)
      • c.链表遍历,不用遍历到NULL,处理NULL很繁琐。
    //执行结果错误,方法不对,努力白费,用这个思路改了好多遍,放弃了这个错误或繁琐的思路。
    
    //没有创建全新的链表,使用L1、L2中较长的保存结果
    class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { unsigned int count1 = 0, count2 = 0;//统计两个链表长度 unsigned int carry = 0; //进位 while (l1 != NULL && l2 != NULL) { l1->val = (l1->val + l2->val + carry) % 10; l2->val = (l1->val + l2->val + carry) % 10; //判断有无进位 if ((l1->val + l2->val + carry) / 10 != 0) carry = 1; else carry = 0; // ((l1->val + l2->val + carry) / 10 != 0)?carry = 1 : carry = 0 ; l1 = l1->next; l2 = l2->next; } if (l1 != NULL) { //L1更长,剩余链表处理 while (l1 != NULL) { l1->val = (l1->val + carry) % 10; if ((l1->val + carry) / 10 != 0) carry = 1; else carry = 0; l1 = l1->next; } if (l1 == NULL && carry == 1) ListNode(1); return l1; } else { //L2更长,剩余链表处理 while (l2 != NULL) { l2->val = (l2->val + carry) % 10; if ((l2->val + carry) / 10 != 0) carry = 1; else carry = 0; l2 = l2->next; } if (l2 == NULL && carry == 1) ListNode(1); return l2; } } };

    3.正确简洁版本

            好的代码应该用比较通用的形式,概括表达出所有可能的情况。代码中红色标注的行是关键行。

    //一般地,建议建立新链表保存结果,不在原链表上直接做修改,因为原链表可能还要使用。
    
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    struct ListNode {
        int val;
        ListNode *next;
        ListNode(int x) : val(x), next(NULL) {}
    };
    
    typedef ListNode* LinkList;
    
    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    
            unsigned int carry = 0; //进位
    
            ListNode* Hl3 = new ListNode(0);//头节点
            ListNode* l3 = Hl3;
    
            int a = 0;
            int b = 0;
            int temp = 0;
              
            while (l1 != NULL || l2 != NULL)
            {
                //判断a和b的取值
                if (l1 == NULL) a = 0;
                else a = l1->val;
                if (l2 == NULL) b = 0;
                else b = l2->val;

    //a = (l1==NULL?) 0 : l1->val;
    //b = (l2==NULL?) 0 : l2->val;
    temp
    = (a + b + carry) % 10; //有无进位 if ((a + b + carry) / 10 != 0) carry = 1; else carry = 0; //创建新结点,保存temp l3->next = new ListNode(temp); l3 = l3->next; if (l1) l1 = l1->next; if (l2) l2 = l2->next; } //最后的进位 if (carry == 1) { l3->next = new ListNode(1); } return Hl3->next; } }; int main() { ListNode* p1 = new ListNode(1); ListNode* p2 = new ListNode(4); ListNode* p3 = new ListNode(3); p1->next = p2; p2->next = p3; p3->next = NULL; ListNode* q1 = new ListNode(5); ListNode* q2 = new ListNode(6); ListNode* q3 = new ListNode(2); q1->next = q2; q2->next = q3; q3->next = NULL; Solution test; ListNode* t1 = test.addTwoNumbers(p1, q1); while (t1) { cout << t1->val << endl; t1 = t1->next; } return 0; }

    //可能的问题:内存泄漏,创建的头节点Hl3最终没有被释放。

    4.用时更少的范例

    //来源:Leetcode官网提交的答案
    //基本思路和方式是相似的

    /*
    * * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ //优化C++I/O提速 static const auto __ = []() { ios::sync_with_stdio(false); cin.tie(nullptr); return nullptr; }(); class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode* L_result = new ListNode(0); ListNode* a = l1; ListNode* b = l2; ListNode*cur = L_result; int carry = 0; while(a != NULL || b != NULL) { int val1 = a != NULL ? a->val : 0; int val2 = b != NULL ? b->val : 0; int sum = val1 + val2 + carry; carry = bool(sum / 10); cur->next = new ListNode(sum %10); //先判是否为空,再赋值 if(a != NULL) { a = a->next; } if(b != NULL) { b = b->next; } cur = cur->next; } if(carry) { cur->next = new ListNode(1); } return L_result->next; } };

    //可能的问题:内存泄漏,创建的头节点L_result最终没有被释放。

    5.两数相加 II

           跳转另一篇博客:Leetcode 445. 两数相加 II

    参考资料:

    1. [LeetCode] Add Two Numbers 两个数字相加

  • 相关阅读:
    在页面生命周期执行时 Page 对象在 SaveState 阶段都发生了什么事?
    接收Firfox RESTClient #Post请求
    c# 单例模式[Singleton]之深夜闲聊
    JQuery 之 Ajax 异步和同步浅谈
    [模板]数学整合
    Yandex插件使用说明——Slager_Z
    模板练习(LUOGU)
    数学整合 新(LUOGU)
    [NOI.AC]DELETE(LIS)
    [NOI.AC]COUNT(数学)
  • 原文地址:https://www.cnblogs.com/paulprayer/p/10029750.html
Copyright © 2011-2022 走看看