[LeetCode-02]-Add Two Numbers-性能极好

2023-11-17

每周完成一个ARTS:(Algorithm、Review、Tip、Share, ARTS)

  • Algorithm: 每周至少做一个 leetcode 的算法题
  • Review: 阅读并点评至少一篇英文技术文章
  • Tip: 学习至少一个技术技巧
  • Share: 分享一篇有观点和思考的技术文章

题目相关

【题目】原题链接
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order 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.

Example:

nput: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

【难度】Medium

Solution

1. 错误的解法

由于是数字,所以想到了先遍历list,将list中存放的数据还原原始数据值,之后再进行加操作,并将结果存放到list中。

代码:

    ListNode *addTwoNumbers_bak(ListNode *l1, ListNode *l2)
    {
        int firstRet = calNumVal(l1);
        int secondRet = calNumVal(l2);

        int sum = firstRet + secondRet;
        printf("%lld + %lld = %lld\n", firstRet, secondRet, sum);

        ListNode *head = new ListNode(sum % 10);
        sum /= 10;
        ListNode *end = head;

        while (sum != 0)
        {
            ListNode *newNode = new ListNode(sum % 10);
            newNode->next = NULL;
            end->next = newNode;
            end = end->next;
            sum /= 10;
        }

        return head;
    }

	//还原为实际数据
    int calNumVal(ListNode *l1)
    {
        int ret = 0;
        int index = 0;

        ListNode *p = l1;
        while (p != NULL)
        {
            ret += p->val * pow(10, index++);
            p = p->next;
        }
        return ret;
    }

但是该代码遇到大一点的数字就不能进行了,所以改为long long后,再次遇到下面更大的测试用例,不能进行。以上代码是上一周实现的,遇到那么大的list,感觉到束手无策,提交代码的时候发现自己的算法不具备通用性,能够计算的数据比较少,未完待续。

一个超长的测试用例:
[2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,9]
[5,6,4,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,9,9,9,9]

2. 正确解法

面对上面那么大数据的测试用例,先计算再存放的方法不可行,所以需要重新思考该题目的方法。经过分析,发现,存放两个加数的 list 以及 存放结果的 list 的存放规律,第一个结点实际上就是数据值的个位,可以直接进行加,在加法的情况下,也最多进位 1。 所以直接采用逐位进行加,把计算的结果存放到最终的 list中。

下面的代码和经典的两个链表进行排序合并算法类似,在两个都非空的情况下,直接进行加,如果其中一个遍历结束,再遍历另一个链表,直到两个都遍历完成。

代码如下:

    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2)
    {
        ListNode *p1 = l1;
        ListNode *p2 = l2;

        ListNode *head = new ListNode(0);
        ListNode *p_ret = head;
        int flag = false; //是否有进位

		//都非空的情况下直接进行加
        while (p1 != NULL && p2 != NULL)
        {
            int temp = p1->val + p2->val;

            //判断上次是否有进位
            if (flag)
            {
                temp += 1;
            }

            //是否有进位,下次使用
            if (temp >= 10)
            {
                flag = true;
            }
            else
            {
                flag = false;
            }

            p_ret->val = temp % 10;

            p1 = p1->next;
            p2 = p2->next;

            if (p1 != NULL && p2 != NULL)
            {
                ListNode *new_node = new ListNode(0);
                new_node->next = NULL;
                p_ret->next = new_node;
                p_ret = new_node;
            }
        }//end while

		//p2或p1遍历结束的情况下,直接进行存放值,不过这里需要考虑进位的情况
		//如下两个while只会执行其中一个
        while (p1 != NULL)
        {
            ListNode *new_node = new ListNode(0);
            new_node->val = p1->val;
            new_node->next = NULL;

            if (flag)
            {
                //连续进位的情况
                int temp = new_node->val + 1;

                if (temp >= 10)
                {
                    flag = true;
                }
                else
                {
                    flag = false;
                }
                new_node->val = temp % 10;
            }

            p_ret->next = new_node;
            p_ret = new_node;

            p1 = p1->next;
        }

        while (p2 != NULL)
        {
            ListNode *new_node = new ListNode(0);
            new_node->val = p2->val;
            new_node->next = NULL;

            if (flag)
            {
                //连续进位的情况
                int temp = new_node->val + 1;

                if (temp >= 10)
                {
                    flag = true;
                }
                else
                {
                    flag = false;
                }
                new_node->val = temp % 10;
            }

            p_ret->next = new_node;
            p_ret = new_node;

            p2 = p2->next;
        }

		//flag为真,说明前面的加法中有进位未处理完成
        if (flag)
        {
            ListNode *new_node = new ListNode(0);
            new_node->val = 1;
            new_node->next = NULL;
            p_ret->next = new_node;

            flag = false;
        }

        return head;
    }

3. 几个用例

一个超长的测试用例
[2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,9]
[5,6,4,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,9,9,9,9]

有进位的用例:
[5]
[5]

连续进位的情况:
[1,1]
[9,9,9]

后记

题目中使用的是不带头结点的单链表,处理起来比较麻烦,总有一些用例跑失败,说明自己的代码没有考虑完全,Accept后发现居然有1563个测试用例,完全通过不容易?。

后来发现,该算法在 C++ 提交的代码中,性能以及空间上都是前1%,牛逼了,也对得起在高铁上调试、提交代码的那个少年。

Runtime: 28 ms, faster than 99.36% of C++ online submissions for Add Two Numbers.
Memory Usage: 10.3 MB, less than 99.45% of C++ online submissions for Add Two Numbers.

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[LeetCode-02]-Add Two Numbers-性能极好 的相关文章

随机推荐

  • 五、格式化namenode出错

    一 报错问题 ERROR conf Configuration error parsing conf yarn site xml com ctc wstx exc WstxParsingException Illegal processin
  • 修改磁盘的io调度算法的方法

    修改磁盘的io调度算法的方法 1 1 临时修改echo noop gt sys block sdb queue scheduler 1 2 永久方法grub中配置增加命令行参数elevator noop 但这个影响是全局的 并且针对所有磁盘
  • 在idea使用GitHub账号、Copilot异常

    登录GitHub显示这样的信息 Invalid authentication data Connection refused connect Failed to initiate the GitHub login process Pleas
  • MacOS Edge GPO via .plist file.

    I created a plist file with the name com microsoft Edge plist Note the name has to be exactly the same and it s case sen
  • vofuria的开发(5)替换原vuforia的茶壶模型、改为自己想要的模型AR model

    1 在基于android NDK开发的过程中 替换目标图片之后就是如何替换掉官方demo中给的茶壶模型 换成自己想要模型 如果对替换目标图片不了解的可以点击这里 2 在更换模型的过程中首先你要有一个 obj的文件 这个文件你可以去下载 也可
  • Python 的垃圾回收机制(GC-GarbageCollection)

    得益于Python的自动垃圾回收机制 在Python中创建对象时无须手动释放 这对开发者非常友好 让开发者无须关注低层内存管理 但如果对其垃圾回收机制不了解 很多时候写出的Python代码会非常低效 垃圾回收算法有很多 主要有 引用计数 标
  • 变参函数的学习

    定义 可变参数函数又称参数个数可变函数 也可以称为变参函数 int printf const char format 其中printf就为典型的变参函数 其中 参数可分为两部分 数目确定的固定参数和数目可变的可选参数 函数至少需要一个固定参
  • = 1.0.1ubuntu2.13)' is not installed' aria-label='The required dependency 'apt (>= 1.0.1ubuntu2.13)' is not installed'> The required dependency 'apt (>= 1.0.1ubuntu2.13)' is not installed

    使用Ubuntu系统的时候 系统提示升级 从14 04升级到16 04时 提示 The required dependency apt gt 1 0 1ubuntu2 13 is not installed 该提示指的是没有安装所需的依赖
  • Django实现教育平台---个人用户中心管理

    修改用户头像 django文件 上传 下面的html的样式省去 上传文件一定要定义enctype
  • ElasticSearch6.x 之IK 分词

    IK分词器介绍 elasticsearch analysis ik git地址 https github com medcl elasticsearch analysis ik 分词方式 Analyzer ik smart ik max w
  • pycharm 有些库(函数)没有代码提示的解决办法

    问题描述 如图 输入变量im 后没有关于第三方库相应的函数或其他提示 当然 此文档的前提是有相关的函数说明以及已有相关设置等 解决方案 python是动态强类型语言 IDE无法判断Image open Me jpg 的返回值类型 无法根据参
  • Git密钥配置

    一 下载并安装Git 官网下载地址点击这里 二 打开git bash 选择一个空文件夹 右键选择 Git Bash Here 三 配置密钥 在Git Bash界面输入git命令 初始化自己的用户名和邮箱 git config global
  • C# string类型(引用类型)

    C string类型 引用类型 2016年03月31日 10 34 45 阅读数 966 sing类型 引用类型 名称 CTS类型 说明 string System String Unicode字符串 string str1 hello s
  • Python教程:类的继承——深入理解继承的概念和用法

    Python教程 类的继承 深入理解继承的概念和用法 类的继承是面向对象编程中的重要概念 它允许我们定义一个新的类 并从现有的类中继承属性和方法 这种继承关系可以让我们在代码中实现代码重用 提高代码的可维护性和可扩展性 在本文中 我们将深入
  • k8s非高可用环境搭建

    k8s非高可用环境搭建 文章目录 k8s非高可用环境搭建 环境准备 集群信息 1 节点规划 2 修改hostname 3 添加hosts解析 4 调整系统配置 5 安装docker 部署kubernetes 1 安装kubernetes k
  • Python 一篇入门

    目录 Python 的简介与特点 Python支持多种编程风格 解释运行 跨平台 可扩展强 可嵌入 丰富的库 Python版本选择 Python开发环境搭建 认识Python解释器 快速入门 变量和赋值 动态类型 变量命名规则 认识 数字
  • Android DataStore 使用详解

    转载请标明出处 http blog csdn net zhaoyanjun6 article details 127358235 本文出自 赵彦军的博客 文章目录 概述 使用 DataStore 本地数据 查看DataStore 文件 Ke
  • Eclipse中JUnit的安装及初始使用

    JUnit的下载 安装 1 下载 http www junit org JUnit软件包 版本很多 可以自行选择 2 在eclipse中添加junit jar包 打开eclipse gt 菜单栏点击project gt properties
  • ubuntu pip intall出现“设备上没有空间”的解决办法

    原因 空间问题呗 东西太多了 tmp盘不够大 pip install的时候文件包会预先下载到tmp盘 步骤1 在home目录下新建一个tmp文件夹 用来取代系统根目录的tmp文件夹 步骤2 设置环境变量TMPDIR export TMPDI
  • [LeetCode-02]-Add Two Numbers-性能极好

    文章目录 题目相关 Solution 1 错误的解法 2 正确解法 3 几个用例 后记 每周完成一个ARTS Algorithm Review Tip Share ARTS Algorithm 每周至少做一个 leetcode 的算法题 R