标签:
【题目】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; }
上面代码也许是长了点,也懒得精简了,欢迎大家帮我精简。
此外,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. 注意考虑进位
标签:
原文地址:http://www.cnblogs.com/lupx/p/leetcode-2.html