Add Two Numbers
Description
You are given two non-empty linked lists representing two non-negative integers. 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.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
具体参考 [LeetCode]
Solution
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode first = null, tmp = null, prev = null;
ListNode temp1 = l1;
ListNode temp2 = l2;
int result = 0, add = 0;
/* first compute thier common bits */
while (temp1 != null) {
if (temp2 == null) break;
/* get the "first" Node of the result */
if (first == null) {
result = temp1.val + temp2.val + add; //Remind the add is necessary;
if (result > 9) {
add = 1;
result -= 10;
} else {
add = 0;
}
first = new ListNode(result);
tmp = prev = first;
} else {
result = temp1.val + temp2.val + add;
if (result > 9) {
add = 1;
result -= 10;
} else {
add = 0;
}
tmp = new ListNode(result);
prev.next = tmp;
prev = tmp;
}
temp1 = temp1.next;
temp2 = temp2.next;
}
/* When the first adder has more bits than the second one */
if (temp1 != null) {
while (temp1 != null) {
result = temp1.val + add;
if (result > 9) {
add = 1;
result -= 10;
} else {
add = 0;
}
tmp = new ListNode(result);
prev.next = tmp;
prev = tmp;
temp1 = temp1.next;
}
}
/* When the second adder has more bits than the second one */
if (temp2 != null) {
while (temp2 != null) {
result = temp2.val + add;
if (result > 9) {
add = 1;
result -= 10;
} else {
add = 0;
}
tmp = new ListNode(result);
prev.next = tmp;
prev = tmp;
temp2 = temp2.next;
}
}
/* the last bit of the result */
if (add != 0) {
tmp = new ListNode(add);
prev.next = tmp;
}
return first;
}
}
Analysis
- 链式结构的运用
- 自己实现加法
Problem & Solution
Overflow
题目并没有很明确地指出测试样例(或者说数据的范围问题),光从题面上思考理解这道题可能会忽略overflow的问题。我这次就犯了这个错误。所以这个问题需要逐一处理。
Wrong approach: 把给出的link node处理成两个数字,相加后把结果处理成字符串再构造link node。
Correct One: 因为是reverse的顺序,低位直接相加,注意进位,多出来的位数加上进位后就是结果的后半部分,结果的前半部分前面低位相加时已经得到。
Wrong code:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int add1 = 0;
ListNode temp = l1;
int multi = 1;
while (temp != null) {
add1 += (temp.val * multi);
multi *= 10;
temp = temp.next;
}
multi = 1;
temp = l2;
int add2 = 0;
while (temp != null) {
add2 += (temp.val * multi);
multi *= 10;
temp = temp.next;
}
int result = add1 + add2;
String tmp = String.valueOf(result);
ListNode first = null;
ListNode[] newOne = new ListNode[tmp.length()];
for (int i = tmp.length() - 1; i >= 0; i--) {
newOne[i] = new ListNode(tmp.charAt(i) - '0');
if (i == tmp.length() - 1) {
first = newOne[i];
} else if (i == 0) {
newOne[i].next = null;
newOne[i+1].next = newOne[i];
} else {
newOne[i+1].next = newOne[i];
}
}
return first;
}
}
Memory Allocation
这次涉及一些内存的分配,然后觉得有些地方还是还是要明确一下的,所以逐一来分析一下。
1.ListNode[] newOne = new ListNode[tmp.length()];
从上图可以看出,在这个new语句过后,事实上是给newOne这个数组分配了2个ListNode大小的空间,但是每一个ListNode都还是null。
2.newOne[i] = new ListNode(tmp.charAt(i) - '0');
这一句才是真正构造了一个ListNode。
3.fault
典型错误:
for (int i = tmp.length() - 1; i >= 0; i--) {
newOne[i] = new ListNode(tmp.charAt(i) - '0');
if (i == tmp.length() - 1) {
first = newOne[i];
newOne[i].next = newOne[i-1];
} else if (i == 0) {
newOne[i].next = null;
} else {
newOne[i].next = newOne[i-1];
}
}
因为是逐位处理的,所以在处理低位时,高位的节点还是null,此时将低位节点i的next指向i-1,就是将他的next指向null,即便后面再生成i-1的节点,i节点的next仍然指向null。
解决办法
1.存储低位节点,生成高位节点时再将低位节点的next指向高位节点
2.先new完所有节点后再处理它们之间的连接关系
END