FTPrep, 2 Add Two Numbers

来源:互联网 发布:mysql的insert into 编辑:程序博客网 时间:2024/05/18 22:53

这道题的思路很简单,但是在实现起来还是有点 not intuitive, 参考了一下别人代码,才有感觉:

1,基本思路是:两条链条的同步后移,这个问题就是每个iteration内 用next实现移动就好

2,不断后移的终止条件其实很简单,就是有一方null了,然后就可以考虑直接copy另一条链的剩下值。“不断”两字,可能就是用while() 来实现。


下面的第二段代码其实才是我最初的思路,考虑的角度,找到局部的终止条件,也就是说什么时候可以一条链停止计算,剩下的任务就是copy剩下一条链。

而第一段代码是一个generalized的思路,比较难直接 意识到,因为他是把整个计算结束的终止条件放在while() 里面,也就是考虑各种可以接续下去的情况,但是要注意,如果一条链表的指针已经是null,那就是保持不用变化。这意味着每个case都需要走O(N)。这个思路其实也很不错的,代码非常精简移动。其中while条件的直观说法:只要l1, l2, carry 任何一个适合计算,那就继续计算,产生新ListNode,这里的三目运算符 用得很巧妙,本质上说 三目运算符 就是一些对于二元选择的最适 实现方式。


另外还有一个值得总结的是:凡是+ 运算,基本上都是模块话的东西,sum,digit,carry; 在List的运算中,dummyNode,curr使得操作极为方便


一个非optimal,但是很精简的代码,思路就是遍历,每次的复杂度都是O(N),如果要优化,在判断条件下就要清楚写出来,那么就不用每次都O(N)了,效率会有所提升

以为是效率40%的代码:

/** * Definition for singly-linked list. * public class ListNode { *     int val; *     ListNode next; *     ListNode(int x) { val = x; } * } */public class Solution {    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {        ListNode dummyNode = new ListNode(-1);        ListNode curr = dummyNode;        int carry = 0;        while(l1!=null || l2!=null || carry!=0){            int sum = ((l1!=null)?l1.val:0) + ((l2!=null)?l2.val:0) + carry;            int digit = sum%10;            carry = sum/10;            curr.next = new ListNode(digit);            curr = curr.next;                        l1=(l1!=null)?l1.next:null;            l2=(l2!=null)?l2.next:null;        }                return dummyNode.next;    }}

自己知道可以优化的地方是:当一个list计算到头了,其实就可以copy另一个list的剩下的值,copy之前还要判断一下是否carry==1,如果yes,还得把这个carry当作一个list,继续加,如果carry==0,则直接copy该链剩下所有值,这要就不用每个case都计算到O(N)了

以下代码效率80+%

/** * Definition for singly-linked list. * public class ListNode { *     int val; *     ListNode next; *     ListNode(int x) { val = x; } * } */public class Solution {    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {        ListNode dummyNode = new ListNode(-1);        ListNode curr = dummyNode;        int carry = 0;        int sum = 0;        int digit = 0;        while(l1!=null && l2!=null){            sum = l1.val + l2.val + carry;            digit = sum%10;            carry = sum/10;            curr.next=new ListNode(digit);            curr = curr.next;                        l1 = l1.next;            l2 = l2.next;        }                while(l1!=null){            if(carry==0){                curr.next=l1;                break;            }            else{                sum = l1.val + 1;                digit = sum%10;                carry = sum/10;                curr.next=new ListNode(digit);                curr = curr.next;                l1 = l1.next;            }        }        while(l2!=null){            if(carry==0){                curr.next=l2;                break;            }            else{                sum = l2.val + 1;                digit = sum%10;                carry = sum/10;                curr.next=new ListNode(digit);                curr = curr.next;                l2 = l2.next;            }        }                if(carry==1) curr.next = new ListNode(1);                return dummyNode.next;    }}


TODO: 尝试用递归的方法来解这道题,无果,有edge case处理不到,就是最后会进位的情况比如2+899。所以要改变ListNode value的问题,用recursion比较难,recursion用在merge 2 sort list,或者是reorder,swap,reverse k-group这些情况会比较无敌,因为没有modify ListNode本身的值。

/** * Definition for singly-linked list. * public class ListNode { *     int val; *     ListNode next; *     ListNode(int x) { val = x; } * } */public class Solution {    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {        if(l1!=null && l1.val==10){            l1.val=0;            if(l1.next==null) l1.next=new ListNode(1);            else l1.next.val+=1;            return addTwoNumbers(l1,l2);        }        if(l2!=null &&l2.val==10){            l2.val=0;            if(l2.next==null) l2.next=new ListNode(1);            else l2.next.val+=1;            return addTwoNumbers(l1,l2);        }        if(l1==null) return l2;        if(l2==null) return l1;        int val=l1.val+l2.val;        l1.val=val%10;        int carry=val/10;        if(carry>0){            if(l1.next!=null){                l1.next.val+=carry;            }            else l1.next=new ListNode(carry);        }        l1.next=addTwoNumbers(l1.next, l2.next);        return l1;    }}


原创粉丝点击