# 题目

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. 对于一段长于另外一段的链表部分,单独处理。
  2. 进位。
  3. 结果之和长于两个链表的情况,如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#)的更多相关文章

  1. 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 ...

  2. 我为什么要写LeetCode的博客?

    # 增强学习成果 有一个研究成果,在学习中传授他人知识和讨论是最高效的做法,而看书则是最低效的做法(具体研究成果没找到地址).我写LeetCode博客主要目的是增强学习成果.当然,我也想出名,然而不知 ...

  3. LeetCode All in One 题目讲解汇总(持续更新中...)

    终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...

  4. [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 ...

  5. 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 ...

  6. Leetcode 笔记 112 - Path Sum

    题目链接:Path Sum | LeetCode OJ Given a binary tree and a sum, determine if the tree has a root-to-leaf ...

  7. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  8. Leetcode 笔记 100 - Same Tree

    题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...

  9. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  10. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

随机推荐

  1. 如何一步一步用DDD设计一个电商网站(四)—— 把商品卖给用户

    阅读目录 前言 怎么卖 领域服务的使用 回到现实 结语 一.前言 上篇中我们讲述了“把商品卖给用户”中的商品和用户的初步设计.现在把剩余的“卖”这个动作给做了.这里提醒一下,正常情况下,我们的每一步业 ...

  2. Partition1:新建分区表

    未分区的表,只能存储在一个FileGroup中:对Table进行分区后,每一个分区都存储在一个FileGroup,或分布式存储在不同的FileGroup中.对表进行分区的过程,是将逻辑上完整的一个表, ...

  3. 23种设计模式--代理模式-Proxy

    一.代理模式的介绍       代理模式我们脑袋里出现第一个词语就是代购,其实就是这样通过一个中间层这个中间成是属于什么都干什么都买得,俗称"百晓生",在平时得开发中我们经常会听到 ...

  4. ASP.NET MVC开发日常一:SessionID合理清除

    在MVC Web开发中临时存储数据一般会用到Session,Cookie,ViewBag,ViewData,TempData.每个的使用场景是不同,具体区别有空再补上. Session数据最敏感,最需 ...

  5. 前端性能优化的另一种方式——HTTP2.0

    最近在读一本书叫<web性能权威指南>谷歌公司高性能团队核心成员的权威之作. 一直听说HTTP2.0,对此也仅仅是耳闻,没有具体研读过,这次正好有两个篇章,分别讲HTTP1.1和HTTP2 ...

  6. Java程序员:工作还是游戏,是该好好衡量一下了

    前阵子我终于下定决心,删掉了硬盘里所有的游戏. 身为一个程序猿,每天都要和各种新技术打交道,闲暇时间,总还得看一下各大论坛,逛逛博客园啥的,给自己充充电.游戏的话,其实我自小就比较喜欢,可以算是一种兴 ...

  7. WPF 普通属性变化通知

    问题描述:使用ObservableCollection<OrderItem> source 给Datagrid.ItemsSource赋值,在后台更新source集合后,前台Datagri ...

  8. ABP领域层

    1.实体Entites 1.1 概念 实体是DDD(领域驱动设计)的核心概念之一. 实体是具有唯一标识的ID且存储在数据库总.实体通常被映射成数据库中的一个表. 在ABP中,实体继承自Entity类. ...

  9. svn常用命令

    1.新建版本库 [root@localhost repos]# mkdir -p project [root@localhost repos]# svnadmin create project [ro ...

  10. Linux命令【第三篇】

    执行下面命令时发现提示需要输入密码,请问提示输入的密码是哪个用户的密码. [test@oldboy ~]$ sudo su - oldboy 解答: 输入当前执行命令test账户的密码. 相关说明: ...