LeetCode(2): Add Two Numbers

【题目】LeetCode(2):  Add  Two Numbers

URL:   https://leetcode.com/problems/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

【中文描述】给2个链表,分别对应了一个数字,链表中每一个元素对应这个数字的其中一位,同时要注意是反序的。例如 2->4->3,代表了数字342, 5->6->4代表了数字465,那么要求计算其和并反序组成链表返回,也即342+465 = 807,返回7->0->8。

—————————————————————————————————————————————————————————————

【初始思路】

刚开始看了半天没看懂题目什么意思,后来又研究了半天例子才搞懂了。面试的时候千万别这样啊。。。

首先立马有个想法:把两个链表反向转变为两个数字,计算其和,然后再将该和反向变为链表返回。

恩,应该可行。而且可以明显看出是个O(n)的算法。暗自窃喜。

 

【灵光一现!】

然而以上想法在实现过程中发现也没想象中那么简单,代码量不小,而且也容易搞错进位的问题。总之撸到一半觉得太不elegant了!本人喜欢elegant的代码!!!

于是重新思考,由于两个链表是反向的,也即list.get(0)实际就是个位数字,这么一看,其实这个顺序反而是合理的。个位先加,然后给出进位,再加十位+进位。以此类推即可得到结果。而且,在算结果的过程中,也是反向的,自然得到要求的链表。这个想法应该很elegant!

【重整思路】

(1) 扫链表是肯定的,给一个for(),int i用来跟踪链表各位。每一次相加和sum = 两链表各位数相加,再加进位。sum>=10的时候,进位=1,该位留sum%10,串入结果list里;若sum<10,此sum直接串入结果list,然后continue。

(2) 考虑特殊情况,如果两个链表长度不等呢?也即,可能一个链表扫完了,另外一个还有几位。还好,数字是反向链表,所以多出来的是高位。那么也简单,循环结束后,进位值是保留的,有进位加进位,没有进位直接串入结果串即可。

【Show Me the Code!!!】

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode p1 = l1;
        ListNode p2 = l2;
        ListNode p = new ListNode(0);
        ListNode node;
        ListNode head = new ListNode(0);
        int upgrade = 0;
        int sum;
        int count = 0;//counts the while times..
        while(p1!=null&&p2!=null){
            //sum one by one
            sum =0;
            sum = upgrade + p1.val + p2.val;
            if(sum>=10){
                upgrade = 1;
            } else {
                //no upgrade digit
                upgrade = 0;
            }
            //sum % = 10;//keep the one-digit
            node = new ListNode(sum%10);
            if(count==0){
                head = node;//get the head, namely the first element of the result Link
            } else {
                p.next = node;
            }
            p = node;
            p1 = p1.next;
            p2 = p2.next;
            count++;
        }
        
        //there may be some elements left
        while(p1!=null){
            //l1 has some left
            sum=0;
            sum = p1.val + upgrade;//we get this upgrade from above while
            if(sum>=10){
                upgrade = 1;
            } else {
                upgrade = 0;
            }
            node = new ListNode(sum%10);
            p.next = node;
            p = node;
            p1 = p1.next;
        }
        while(p2!=null){
            sum=0;
            sum = p2.val + upgrade;
            if(sum>=10){
                upgrade = 1;
            } else {
                upgrade = 0;
            }
            node = new ListNode(sum%10);
            p.next = node;
            p = node;
            p2 = p2.next;
        }
        if(upgrade==1){//the very last upgrade number
            node = new ListNode(1);
            p.next = node;
        }
        //only one among the two whiles above could be done!
        return head;
    }
Add Two Numbers

 

上面代码也许是长了点,也懒得精简了,欢迎大家帮我精简。

此外,ListNode是LeetCode的OJ已经提供了定义,直接使用就好,不需要自己再定义一遍。

【总结一下】

1. 在两个链表/数组需要合并、同时逐元素作互操作的时候,基本上需要3个指针,一个p1指向第一个链表/数组,一个p2指向第二个链表/数组,一个p指向两者相互作用的结果(本题为结果list);

    所以通常的结构如下:

     while(p1.notTheEndOfls1 && p2.notTheEndOfls2){

           // do what you gotta do...

     } 

     while(p1.notTheEndOfls1) {

          // deal with the elements left in ls1

     }

     while(p2.notTheEndOfls2) {

          // deal with the elements left in ls2

     }

     看似长,但是上面写法可以避免出现遗漏。且2、3两个while显然只会执行一个。

2. 注意考虑进位

 

posted @ 2015-09-05 09:55  RockIt  阅读(485)  评论(0编辑  收藏  举报