题目连接:2.两数相加

题意

题目难度标为 中等, 因为题意上有一部分理解难度,以及需要数据结构的链表基础。

还不知道到链表的童鞋可以粗略的看下百度百科或者是翻出数据结构的书看一看,通俗一点的语言来解释链表就是:上线和下线

上线知道自己的下线,但不知道自己下线的下线,同时也不知道自己的上线是谁。

这就是单向链表

这道题的题意就是将两个数字变成了两个单向链表,其中每一个节点存储一位数字,且是逆序存放,也就是倒过来存了。

解题思路

首先来想一下不同情况和对应的案例:

  1. 两个链表长度相等。

输入:(2 -> 4 -> 3) + (5 ->6 -> 4)

输出:(7 -> 0 -> 8)

  1. 两个链表长度不等。

输入:(2 -> 4) + (5 -> 6 -> 4)

输出:(7 -> 0 -> 5)

  1. 最终结果的最高位存在进位的情况。

输入:(2 -> 4 -> 5) + (5 -> 6 -> 4)

输出:(7 -> 0 -> 0 -> 1)

解题的关键便是:合并链表并且保证进位正确

模拟进位

首先我们按位相加,然后再对每一位进行进位处理,满 10 则进 1

代码:

    public class Solution
{
public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
ListNode first = null;
ListNode current = null;
IList<int> sums = new List<int>();
int sum = 0;
int res = 0; while (l1 != null || l2 != null)
{
sum = res;
if (l1 != null)
{
sum += l1.val;
l1 = l1.next;
} if (l2 != null)
{
sum += l2.val;
l2 = l2.next;
} res = sum / 10;
sum %= 10;
sums.Add(sum);
} if(res > 0) sums.Add(res); if(sums.Any()) first = new ListNode(sums[0]); current = first; for (int i = 1; i < sums.Count; i++)
{
current.next = new ListNode(sums[i]);
current = current.next;
} return first;
}
}

执行用时: 252 ms, 在所有 C# 提交中击败了13.33%的用户

内存消耗: 26.7 MB

这个耗时有点凄惨,接近垫底了。那也说明了还有很大的优化空间。

优化常量

上面我们在循环时使用到了 IListCount,这里我们可以提前将其存储起来。

代码如下:

    public class Solution
{
public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
ListNode first = null;
ListNode current = null;
IList<int> sums = new List<int>();
int sum = 0;
int res = 0;
int count = 0; while (l1 != null || l2 != null)
{
sum = res;
if (l1 != null)
{
sum += l1.val;
l1 = l1.next;
} if (l2 != null)
{
sum += l2.val;
l2 = l2.next;
} res = sum / 10;
sum %= 10;
sums.Add(sum);
} if (res > 0) sums.Add(res); count = sums.Count; if (count > 0) first = new ListNode(sums[0]); current = first; for (int i = 1; i < count; i++)
{
current.next = new ListNode(sums[i]);
current = current.next;
} return first;
}
}

执行用时: 164 ms, 在所有 C# 提交中击败了85.62%的用户

内存消耗: 26.8 MB

仅仅是替换了一个变量,执行用时就优化了近 100ms! 这 100ms 就超过了 70% 的提交。

前面还有近 15% 说明还有优化空间。

优化循环数

上面的算法,如果按照大O表示法来计算复杂度的话,它的复杂度是:O(max(l1.Length, l2.Length)) ,再精简一下也就是 O(n),即单重循环的程度。

但真正的复杂度是(同样也是估算,循环内的操作数没有算进来,这里只算了循环的):2 * max(l1.Length, l2.Length) + 1。因为这里实际上是使用了两个循环。那么我们可以将这个复杂度表达式中的倍数 : 2 去掉,即只用一重循环。

代码如下:

    public class Solution
{
public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
ListNode first = null;
ListNode current = null;
int sum = 0;
int res = 0; while (l1 != null || l2 != null)
{
sum = res;
if (l1 != null)
{
sum += l1.val;
l1 = l1.next;
} if (l2 != null)
{
sum += l2.val;
l2 = l2.next;
} res = sum / 10;
sum %= 10; if (current == null)
{
first = new ListNode(sum);
current = first;
}
else
{
current.next = new ListNode(sum);
current = current.next;
}
} if (res > 0) current.next = new ListNode(res); return first;
}
}

执行用时: 136 ms, 在所有 C# 提交中击败了98.85%的用户

内存消耗: 26.5 MB

在我们移除掉一重循环之后,执行用时优化了 20 多ms(为什么不是优化了近一半的时间?),而这 20 多ms就又超过了 13% 的提交。

对于Leetcode判题耗时的思考

处于对连续两道题目都没有办法达到最优(至少前 1% )的情况下,若羽今天写到这里时,特意去看了一下耗时最短的代码(104ms),复制下来之后直接提交,结果显示是 248ms !??

再次提交之后结果显示是 160 ms !??

同一份代码, 上下浮动的区间未免也太大了!若羽不禁思考起 LeetCode 的判题核心是如何进行计时的。这个浮动区间已经达到可以破坏排名公平性的程度了,也许有人会觉得若羽危言耸听,夸大其词。

事实是:确实已经达到破坏公平的程度了!!!,这一类在线运行代码并且自动输入案例比对结果的系统其实很早就已经出现,在 信息学竞赛 以及 ACM大学生程序设计竞赛 中通常被称为 OJ(Online Judge System) 在线判题系统。而在竞赛场上,差距达到 160ms 意味着什么?意味着两队选手同时甚至略迟一点点提交代码,最终谁的排名在前还得听天命

抛开竞赛的立场,浮动如此大的排名,在一定程度上已经无法再客观的去评价时间复杂度相近算法的优劣了。排名第一的算法再运行一次也有可能会排到末尾去。

但是算法优化的思路还是可以继续,撸码不停,优化不止~(好想自己实现一个 OJ 了!)

LeetCode :2.两数相加 解题报告及算法优化思路的更多相关文章

  1. LeetCode :1.两数之和 解题报告及算法优化思路

    最近开始重拾算法,在 LeetCode上刷题.顺便也记录下解题报告以及优化思路. 题目链接:1.两数之和 题意 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 ...

  2. leetcode之两数相加解题思路

    问题描述 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数组中同一个元素不能使 ...

  3. Leetcode 002. 两数相加

    1.题目描述 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表 ...

  4. LeetCode 445——两数相加 II

    1. 题目 2. 解答 2.1 方法一 在 LeetCode 206--反转链表 和 LeetCode 2--两数相加 的基础上,先对两个链表进行反转,然后求出和后再进行反转即可. /** * Def ...

  5. Leetcode 445. 两数相加 II

    1.题目描述 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头. ...

  6. LeetCode 445. 两数相加 II(Add Two Numbers II)

    445. 两数相加 II 445. Add Two Numbers II 题目描述 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个 ...

  7. LeetCode 2. 两数相加(Add Two Numbers)

    2. 两数相加 2. Add Two Numbers 题目描述 You are given two non-empty linked lists representing two non-negati ...

  8. LeetCode 2——两数相加(JAVA)

    给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和 ...

  9. LeetCode 2. 两数相加(Add Two Numbers)

    题目描述 给定两个非空链表来表示两个非负整数.位数按照逆序方式存储,它们的每个节点只存储单个数字.将两数相加返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头. 示例: 输入: ...

随机推荐

  1. Mybatisの常见面试题

    Mybatis -面试问题 最近准备系统的学一下Mybatis,之前只有粗略的看了下,选了十个常见的面试题 1. #{}和${}的区别是什么? #{}是预编译处理,${}是字符串替换. Mybatis ...

  2. 关于Lombok和自动生成get set方法

    在Java开发的项目里面免不了要用很多的get set 以及toString之类的方法,有时候确实是很繁琐而且做着重复共同工作,我们有没有办法来简化这个过程呢,当然有. Lombok就可以很好的解决这 ...

  3. leadcode的Hot100系列--78. 子集--位运算

    看一个数组的子集有多少,其实就是排列组合, 比如:[0,1] 对应的子集有:[] [0] [1] [1,1] 这四种. 一般对应有两种方法:位运算 和 回溯. 这里先使用位运算来做. 位运算 一个长度 ...

  4. 并发编程-concurrent指南-Lock-可重入锁(ReentrantLock)

    可重入和不可重入的概念是这样的:当一个线程获得了当前实例的锁,并进入方法A,这个线程在没有释放这把锁的时候,能否再次进入方法A呢? 可重入锁:可以再次进入方法A,就是说在释放锁前此线程可以再次进入方法 ...

  5. springMVC java.lang.IllegalStateException: getOutputStream() has already bee

    在导出文件的时候,一直报这个错误. 网上一般的做法是out.clear();或者使用servlet或者Action返回null. 试过了这些方法都不成功. 最后直到试了在jsp重定向的方法才成功了. ...

  6. Java学习笔记之---API的应用

    Java学习笔记之---API的应用 (一)Object类 java.lang.Object 类 Object 是类层次结构的根类.每个类都使用 Object 作为超类.所有对象(包括数组)都实现这个 ...

  7. Linux关闭进程。

    一.shell命令根据端口后关闭指定进程. $(netstat -nlp | | awk '{print $7}' | awk -F"/" '{ print $1 }') nets ...

  8. JS代码实现复制功能

    本人没什么基础看了好久百度,不知道为什么在百度上问一个js实现copy功能会多出那么多代码出来,感觉废话一堆效果还没能达到需要复制 的效果. 然而在我看来,js复制代码 无非就那么几句罢了.原生cop ...

  9. python介绍、安装及相关语法、python运维、编译与解释

    1.python介绍 Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/)是一种广泛使用的解释型.高级编程.通用型编程语言,由吉多.范罗苏姆创造,第一版发布于1991年.可以视 ...

  10. import tensorflow 报错

    >>> import tensorflowe:\ProgramData\Anaconda3\lib\site-packages\h5py\__init__.py:36: Future ...