LeetCode 445. Add Two Numbers II

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjxxyz123/article/details/79978811

问题描述

  • 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;
    }
阅读更多

Add Two Numbers的问题

08-02

求助,LeetCode OJ 上的第二题Add Two Numbers,不熟练链表的我卡在这儿了,两个被加数位数相同算法没问题,位数不相同执行就当了。。。。一直没看出什么问题,调试器只有gdb,不会用。求大神帮忙看看是什么问题,跪谢。rnrn/*Add two numbersrn You are given two linked lists representing two non-negative numbers. rn The digits are stored in reverse order and each of their nodes contain a single digit. rn Add the two numbers and return it as a linked list.rn rn Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)rn Output: 7 -> 0 -> 8rn*/rnrn//定义简单结点rnstruct ListNode rn int val;rn ListNode *next;rn ListNode(int x) : val(x), next(NULL) rn;rnrn//创建解决方案rnclass Solution rnpublic:rn ListNode* addTwoNumbers( ListNode* l1, ListNode* l2 ) rn ListNode *pHead , *pCurr; //定义头指针 , 当前指针rn int sum , val1 , val2 , carry; //定义和,被加数1,被加数2,进位数rn pHead = ( ListNode * )malloc( sizeof( ListNode ) ); //创建第一个结点rn pCurr = pHead; //初始化当前结点rn carry = 0; //初始化进位数rn while( l1 != NULL || l2 != NULL ) //循环直到两个被加数的当前指针都为空rn rn val1 = l1 != NULL ? l1->val : 0; //为被加数赋值rn val2 = l2 != NULL ? l2->val : 0;rn rn sum = ( val1 + val2 + carry ) % 10; //求和rn carry = ( val1 + val2 + carry ) / 10; //求进位rn rn pCurr->val = sum; //为储存结果的链表添加数字rn if ( l1->next != NULL || l2->next != NULL) //储存结果的链表添加下一个结点rn pCurr->next = ( ListNode * )malloc( sizeof( ListNode ) );rn pCurr = pCurr->next;rn rn rn if ( l1 != NULL ) //被加数指针下移rn l1 = l1->next;rn rn if ( l2 != NULL )rn l2 = l2->next;rn rn rn rn if ( carry != 0) //循环结束进位结算rn pCurr->next = ( ListNode * )malloc( sizeof( ListNode ) );rn pCurr = pCurr->next;rn pCurr->val = carry;rn rn rn pCurr->next = NULL;rn rn return pHead; //输出结果rn rn;

没有更多推荐了,返回首页