LeetCode 445. Add Two Numbers II

原创 2018年04月17日 18:25:16

问题描述

  • You are given two non-empty linked lists representing two non-negative integers. The most significant digit comes first 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.
    Follow up:
    What if you cannot modify the input lists? In other words, reversing the lists is not allowed.
  • Example:

Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 8 -> 0 -> 7

问题分析

  • 该题是 LeetCode 2. Add Two Numbers 的进阶题,原题是最低位在链表头部,该题是最高位在链表头部。如果反转链表后计算的话,十分容易,但题目要求不能反转链表,再加上这是链表,不是数组,所以相对麻烦一些
  • 解法1 : 用实现“反转链表”的功能
  • 解法2 : 用递归(实际还是栈)
  • 解法3: 利用找新链表中的最右边的第一个非 9 的节点,来处理进位信息
    其实方法还是来源于 LeetCode 的另一道题目,[LeetCode] Plus One Linked List 链表加一运算 , 以及 LeetCode 66. Plus One
    思路是遍历链表,找到右起第一个不为9的数字,如果找不到这样的数字,说明所有数字均为9,那么在表头新建一个值为0的新节点,进行加1处理,然后把右边所有的数字都置为0即可。举例来说:
    比如1->2->3,那么第一个不为9的数字为3,对3进行加1,变成4,右边没有节点了,所以不做处理,返回1->2->4。
    再比如说8->9->9,找第一个不为9的数字为8,进行加1处理变成了9,然后把后面的数字都置0,得到结果9->0->0。
    再来看9->9->9的情况,找不到不为9的数字,那么再前面新建一个值为0的节点,进行加1处理变成了1,把后面的数字都置0,得到1->0->0->0。
    至于该题的情况,有进位就需要将新链表(尚未加入当前产生进位信息的节点)加1 ,所以只要实时维护新链表中右起第一个不为9的数字的位置即可。有进位时,该位置加1,该位置后面所有值都为0。更加复杂。
    并且,还要注意虚拟节点的使用

经验教训

  • 递归处理链表问题,还是十分好用的
  • 解法3这种奇淫技巧!!!

代码实现

  • 解法1
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if (l1 == null || l2 == null) {
            return null;
        }
        ListNode cur1 = l1;
        ListNode cur2 = l2;
        Stack<Integer> s1 = new Stack<>();
        Stack<Integer> s2 = new Stack<>();
        ListNode addedList = null;
        while (cur1 != null) {
            s1.push(cur1.val);
            cur1 =cur1.next;
        }
        while (cur2 != null) {
            s2.push(cur2.val);
            cur2 = cur2.next;
        }
        int carry = 0;
        while (!s1.isEmpty() || !s2.isEmpty()) {
            int val = 0;
            if (!s1.isEmpty()) {
                val += s1.pop();
            }
            if (!s2.isEmpty()) {
                val += s2.pop();
            }
            val += carry;
            ListNode newHead = new ListNode(val % 10);
            newHead.next = addedList;
            addedList = newHead;
            carry = val / 10;
        }
        if (carry != 0) { //处理进位信息
            ListNode newHead = new ListNode(1);
            newHead.next = addedList;
            return newHead;
        }
        return addedList;
    }
  • 解法2
     public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if (l1 == null || l2 == null) {
            return null;
        }
        int length1 = getLength(l1);
        int length2 = getLength(l2);
         //确保长链以及短链
        ListNode res = length1 > length2 ? addTwoNumbers(l1, l2, length1 - length2) : addTwoNumbers(l2, l1, length2 - length1);
         //处理最高位信息
        if (res.val > 9) {
            res.val = res.val % 10;
            ListNode newHead = new ListNode(1);
            newHead.next = res;
            return newHead;
        }
         return res;
     }
    //统计长度
    public int getLength(ListNode head) {
        ListNode curNode = head;
        int length = 0;
        while (curNode != null) {
            ++length;
            curNode = curNode.next;
        }
        return length;
    }
    //已知 l1长度大于l2长度offset,对两链表进行"相加", 9 -> 6 -> 3 与 5 - > 8 相加结果为 10 -> 2 -> 1
    //也就是对最高位的进位不处理
    public ListNode addTwoNumbers(ListNode l1, ListNode l2, int offset) {
        //base case
        if (l1 == null) {
            return null;
        }
        //当前位的相加结果
        ListNode curRes = offset == 0 ? new ListNode(l1.val + l2.val) : new ListNode(l1.val);
        //递归得出 下一位的相加结果
        ListNode nextRes = offset == 0 ? addTwoNumbers(l1.next, l2.next, offset) : addTwoNumbers(l1.next, l2, offset - 1);
        //根据下一位的结果,修正当前结果以及下一位结果
        if (nextRes != null && nextRes.val > 9) {
            curRes.val += 1;
            nextRes.val = nextRes.val % 10;
        }
        //连接
        curRes.next = nextRes;
        //返回整体相加后结果
        return curRes;
    }
  • 解法3
     public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if (l1 == null || l2 == null) {
            return null;
        }
         int diff = getLength(l1) - getLength(l2);
         //让 l1指向长链表,l2指向短链表
        if (diff < 0) {
            ListNode temp = l1;
            l1 = l2;
            l2 = temp;
        }
        diff = Math.abs(diff);
        //虚拟节点
        ListNode dummy = new ListNode(0);
         //新形成链表的尾部
         ListNode tail = dummy;
         //指向新链表中 :从右起第一个不为9的节点(它的后面全是 9)
         ListNode lastNot9 = dummy;
         ListNode cur1 = l1;
         //将长链表多于的一部分(不参与加法)直接加入新链表,并更新lastNot9
         while (diff > 0) {
             tail.next = new ListNode(cur1.val);
             tail = tail.next;
             if (tail.val != 9) {
                 lastNot9 = tail;
             }
              cur1 = cur1.next;
             --diff;
         }
         //两链表相加
         ListNode cur2 = l2;
         while (cur1 != null) {
             int val = cur1.val + cur2.val;
             //如果当前值大于10
             if (val >= 10) {
                 val -= 10;
                 //新链表中,从右起第一个不为9的节点加1,进位的原因
                 ++lastNot9.val;
                 //该节点后面节点全部置为0,因为原先都为9,一发生进位变为0
                 ListNode is9 = lastNot9.next;
                 while (is9 != null) {
                     is9.val = 0;
                     is9 = is9.next;
                 }
             }
             tail.next = new ListNode(val);
             //更新lastNot9
            lastNot9 = val != 9 ? tail.next : lastNot9;
             tail = tail.next;
             cur1 = cur1.next;
             cur2 = cur2.next;
         }
         //dummy.val == 1 说明 原链表中第一位相加后结果为9,但因进位,又多了一位。
         return dummy.val == 1 ? dummy : dummy.next;
     }

    //统计长度
    public int getLength(ListNode head) {
        ListNode curNode = head;
        int length = 0;
        while (curNode != null) {
            ++length;
            curNode = curNode.next;
        }
        return length;
    }
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjxxyz123/article/details/79978811

Microsoft Agent技术在Delphi中的应用

解放军合肥炮兵学院 张建军 中保财险安徽省铜陵市分公司 韩莹 ---- Microsoft Agent是微软公司于1997年9月发布的一项代理软件开发技术,而后被集成到Internet Explore...
  • deardelphi
  • deardelphi
  • 2000-08-26 10:06:00
  • 689

leetcode-445. Add Two Numbers II

#leetcode-445. Add Two Numbers II
  • u011518120
  • u011518120
  • 2016-11-14 14:14:11
  • 1067

【LeetCode】445. Add Two Numbers II 解题报告(Python)

【LeetCode】445. Add Two Numbers II 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/prob...
  • fuxuemingzhu
  • fuxuemingzhu
  • 2018-02-26 18:22:49
  • 48

LeetCode笔记:445. Add Two Numbers II

相加两个用链表表示的数字
  • Cloudox_
  • Cloudox_
  • 2017-01-07 14:29:09
  • 1398

leetcode 445 Add Two Numbers II C++

这道题做出来很简单,但是运行时间总是不能小于40ms。 看了下discuss,最快的方法就是不用栈,两个指针从后往前走。 我是用栈的,但是比别的用栈的慢了不少,最后发现原因是用了太多的临时变量,以...
  • a2331046
  • a2331046
  • 2016-12-28 20:56:31
  • 369

LeetCode-445. Add Two Numbers II (JAVA)链表数字加法

LeetCode-445. Add Two Numbers II (JAVA)链表数字加法
  • mine_song
  • mine_song
  • 2017-04-23 21:26:19
  • 547

445. Add Two Numbers II

445. Add Two Numbers II You are given two linked lists representing two non-negative numbers. T...
  • liuchenjane
  • liuchenjane
  • 2016-10-31 19:49:48
  • 817

LeetCode: 445. Add Two Numbers II 单链表加法

445. Add Two Numbers IIProblem descriptionYou are given two linked lists representing two non-negati...
  • eswai
  • eswai
  • 2016-10-30 01:57:41
  • 903

leetcode_445. Add Two Numbers II 单链表表示的两个大数相加

题目: You are given two non-empty linked lists representing two non-negative integers. The most s...
  • qqzj_bupt
  • qqzj_bupt
  • 2017-01-05 20:51:41
  • 527

2、add two numbers(python)

You are given two linked lists representing two non-negative numbers. The digits are stored in rever...
  • qq_28119401
  • qq_28119401
  • 2016-09-18 21:49:47
  • 627
收藏助手
不良信息举报
您举报文章:LeetCode 445. Add Two Numbers II
举报原因:
原因补充:

(最多只允许输入30个字)