LeetCode-2AddTwoNumbers(C#)
# 题目
2. Add Two Numbers
You are given two linked lists representing two non-negative numbers. 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.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
# 思路
不知道各位能不能看懂题目,简单解释一下,就是把整数每一位颠倒进行加法。题目中给出的例子,最初对应342 + 465 = 807,然后颠倒变成243 + 564 = 708,在转换为链表。
这下题目给出链表的定义,我们需要对这种类型的链表进行操作。
// Definition for singly-linked list.
public class ListNode
{
public int val;
public ListNode next;
public ListNode(int x) { val = x; }
}
方法一:普通遍历,链表l1和l2相应位置相加,再加进位,存入链表result中。
注意点:
- 对于一段长于另外一段的链表部分,单独处理。
- 进位。
- 结果之和长于两个链表的情况,如1 + 999 = 1000。
普通遍历,时间复杂度O(n),空间复杂度O(n),时间204ms。
// normal traversal: time O(n) space O(n) result: 204ms
public void calculateSum(ListNode tresult, ref int carry, int sum)
{
)
{
carry = ;
tresult.next = );
}
else
{
carry = ;
tresult.next = new ListNode(sum);
}
}
public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
ListNode tl1 = l1, tl2 = l2;
ListNode result = );
ListNode tresult = result;
;
// both ListNode 1 and ListNode 2 have values
while (tl1 != null && tl2 != null)
{
calculateSum(tresult, ref carry, tl1.val + tl2.val + carry);
tl1 = tl1.next;
tl2 = tl2.next;
tresult = tresult.next;
}
// Debug.Assert(!(tl1 != null && tl2 != null), "tl1 and tl2 aren't null");
// either ListNode 1 or ListNode 2 has values (maybe) and don't forget carry.
while (tl1 != null)
{
calculateSum(tresult, ref carry, tl1.val + carry);
tl1 = tl1.next;
tresult = tresult.next;
}
while (tl2 != null)
{
calculateSum(tresult,ref carry, tl2.val + carry);
tl2 = tl2.next;
tresult = tresult.next;
}
// at this time, ListNode 1 and ListNode 2 should be null, however, carry could be null or not
// Debug.Assert(tl1 == null && tl2 == null, "calculation doesn't finish");
) tresult.next = );
// neither ListNode 1 nor ListNode 2 have values
return result.next;
}
*/
方法二:空间优化遍历,链表l1和l2相应位置相加,再加进位,存入链表l1中。方法二的代码没有方法一的代码清晰。
空间优化遍历,时间复杂度O(n),空间复杂度O(1),时间208ms。
// use ListNode 1 to restore result
// space (and time, I think, but result doesn't prove) optimized traversal: time O(n) space O(1) result: 208ms
public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
if (l1 == null) return l2;
if (l2 == null) return l1;
, sum = ;
ListNode pre = null, result = l1;
)
{
// calculate sum and carry
sum = ;
if (l1 != null) sum += l1.val;
if (l2 != null)
{
sum += l2.val;
l2 = l2.next; // ListNode1 will be used below, ListNode2 not, so if ListNode 2 next exists, ListNode 2 move to next
}
sum += carry;
)
{
carry = ;
sum -= ;
}
else
{
carry = ;
}
// find a place for sum in ListNode 1, l1 is in use
if (l1 != null)
{
pre = l1;
) sum -= ;
l1.val = sum;
l1 = l1.next;
}
else
{
) sum -= ;
pre.next = new ListNode(sum);
pre = pre.next;
}
}
return result;
}
*/
方法三:递归,链表l1和l2相应位置相加,再加进位,存入链表node中。速度最快,是比较好的解决方案。
# 解决(递归)
递归,时间复杂度O(n),空间复杂度O(n),时间196ms。
// recursive tranversal: time O(n) space:O(n) time: 196ms (why it is faster than normal loop)
public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
);
}
public ListNode AddTwoNumbers(ListNode l1, ListNode l2, int carry)
{
) return null;
// calculate sum
;
if (l1 != null) sum += l1.val;
if (l2 != null) sum += l2.val;
sum += carry;
)
{
carry = ;
sum -= ;
}
else
{
carry = ;
}
// set node's next and val and return
ListNode node = new ListNode(sum);
node.next = AddTwoNumbers(l1 != null ? l1.next : null, l2 != null ? l2.next : null, carry);
return node;
}
# 题外话
为何递归会比循环快呢?百思不得其解,若有高人知道,请指教。
# 测试用例
static void Main(string[] args)
{
_2AddTwoNumbers solution = new _2AddTwoNumbers();
ListNode l1 = );
ListNode l2 = );
ListNode result = );
// ListNode doesn't have a null constructor, so we can igonore this case
Debug.Assert(Test.match(solution.AddTwoNumbers(l1, l2), result), "wrong 1");
// ListNode 1 length is larger than ListNode 2 length
l1 = );
l1.next = );
l1.next.next = );
l2 = );
result.next = );
result.next.next = );
Debug.Assert(Test.match(solution.AddTwoNumbers(l1, l2), result), "wrong 2");
// ListNode 2 length is larger than ListNode 1 length and has carries
l1 = );
l1.next = );
l2 = );
l2.next = );
l2.next.next = );
result = );
result.next = );
result.next.next = );
result.next.next.next = );
Debug.Assert(Test.match(solution.AddTwoNumbers(l1, l2), result), "wrong 3");
}
class Test
{
public static bool match(_2AddTwoNumbers.ListNode l1, _2AddTwoNumbers.ListNode l2)
{
_2AddTwoNumbers.ListNode tl1 = l1, tl2 = l2;
while(tl1 != null && tl2 != null)
{
if (tl1.val != tl2.val) return false;
tl1 = tl1.next;
tl2 = tl2.next;
}
if (tl1 == null && tl2 == null) return true;
else return false;
}
}
# 地址
Q: https://leetcode.com/problems/add-two-numbers/
A: https://github.com/mofadeyunduo/LeetCode/tree/master/2AddTwoNumbers
(希望各位多多支持本人刚刚建立的GitHub和博客,谢谢,有问题可以邮件609092186@qq.com或者留言,我尽快回复)
LeetCode-2AddTwoNumbers(C#)的更多相关文章
- LeetCode in action
(1) Linked List: 2-add-two-numbers,2.cpp 19-remove-nth-node-from-end-of-list,TBD 21-merge-two-sorted ...
- 我为什么要写LeetCode的博客?
# 增强学习成果 有一个研究成果,在学习中传授他人知识和讨论是最高效的做法,而看书则是最低效的做法(具体研究成果没找到地址).我写LeetCode博客主要目的是增强学习成果.当然,我也想出名,然而不知 ...
- LeetCode All in One 题目讲解汇总(持续更新中...)
终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...
- [LeetCode] Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子字符串
Find the length of the longest substring T of a given string (consists of lowercase letters only) su ...
- Leetcode 笔记 113 - Path Sum II
题目链接:Path Sum II | LeetCode OJ Given a binary tree and a sum, find all root-to-leaf paths where each ...
- Leetcode 笔记 112 - Path Sum
题目链接:Path Sum | LeetCode OJ Given a binary tree and a sum, determine if the tree has a root-to-leaf ...
- Leetcode 笔记 110 - Balanced Binary Tree
题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...
- Leetcode 笔记 100 - Same Tree
题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...
- Leetcode 笔记 99 - Recover Binary Search Tree
题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...
- Leetcode 笔记 98 - Validate Binary Search Tree
题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...
随机推荐
- 如何一步一步用DDD设计一个电商网站(五)—— 停下脚步,重新出发
阅读目录 前言 单元测试 纠正错误,重新出发 结语 一.前言 实际编码已经写了2篇了,在这过程中非常感谢有听到观点不同的声音,借着这个契机,今天这篇就把大家提出的建议一个个的过一遍,重新整理,重新出发 ...
- AngularJS过滤器filter-保留小数,小数点-$filter
AngularJS 保留小数 默认是保留3位 固定的套路是 {{deom | number:4}} 意思就是保留小数点 的后四位 在渲染页面的时候 加入这儿个代码 用来精确浮点数,指定小数点 ...
- [原创]mybatis中整合ehcache缓存框架的使用
mybatis整合ehcache缓存框架的使用 mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓 ...
- Mysql事务探索及其在Django中的实践(一)
前言 很早就有想开始写博客的想法,一方面是对自己近期所学知识的一些总结.沉淀,方便以后对过去的知识进行梳理.追溯,一方面也希望能通过博客来认识更多相同技术圈的朋友.所幸近期通过了博客园的申请,那么今天 ...
- Android GridView 通过seletor 设置状态和默认状态
Android中可以通过selector控制GridView Item 的状态,而省去使用代码控制 GridView View Selector Xml文件 <?xml version=&quo ...
- jquery.Callbacks的实现
前言 本人是一个热爱前端的菜鸟,一直喜欢学习js原生,对于jq这种js库,比较喜欢理解他的实现,虽然自己能力有限,水平很低,但是勉勉强强也算是能够懂一点吧,对于jq源码解读系列,博客园里有很多,推荐大 ...
- 【手把手】JavaWeb 入门级项目实战 -- 文章发布系统 (第十二节)
好的,那么在上一节中呢,评论功能的后台已经写好了,这一节,先把这部分后台代码和前台对接一下. 1.评论功能实现 我们修改一下保存评论按钮的点击事件,用jQuery的方式获取文本框中的值,然后通过aja ...
- Objective-C枚举的几种定义方式与使用
假设我们需要表示网络连接状态,可以用下列枚举表示: enum CSConnectionState { CSConnectionStateDisconnected, CSConnectionStateC ...
- maven 中snapshot版本和release版本的区别
maven中的仓库分为两种,snapshot快照仓库和release发布仓库.snapshot快照仓库用于保存开发过程中的不稳定版本,release正式仓库则是用来保存稳定的发行版本.定义一个组件/模 ...
- Android Fragment 剖析
1.Fragment如何产生?2.什么是Fragment Android运行在各种各样的设备中,有小屏幕的手机,超大屏的平板甚至电视.针对屏幕尺寸的差距,很多情况下,都是先针对手机开发一套App,然后 ...