題目描述
給出兩個非空
的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照逆序
的方式存儲的,並且它們的每個節點只能存儲一位
數字。
如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。
您可以假設除了數字0
之外,這兩個數都不會以0
開頭。
示例:
輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807
題目解析
這個題目的意思看起來其實很簡單,提供了兩個鏈表,每個鏈表代表一個非負整數,它們各自的位數是按照逆序
方式存儲的,例如:(2 -> 4 -> 3)
代表整數342
,(5 -> 6 -> 4)
則代表整數465
,兩數相加的結果自然是807,這就是我們要給出的答案,但是要用鏈表的形式返回7 -> 0 -> 8
。題目中說明了是非空鏈表,所以就不用考慮鏈表為null的情況了。
乍眼一看,很簡單啊,不就是把兩個數相加嘛,我先把它整成整數,然后相加,最后把結果整成鏈表,完美,哈哈哈哈,簡直被自己的聰明才智給折服。
翻車嘗試1:蝦扯蛋法
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head1 = l1;
ListNode head2 = l2;
int i = 0;
int j = 0;
int index = 0;
// 將鏈表l1轉化為整數
while (head1 != null) {
i += head1.val * Math.pow(10, index);
index++;
head1 = head1.next;
}
index = 0;
// 將鏈表l2轉化為整數
while (head2 != null) {
j += head2.val * Math.pow(10, index);
index++;
head2 = head2.next;
}
int sum = i + j;
ListNode newHead = new ListNode(0);
ListNode tmpHead = newHead;
int sign = 0;
// 將結果轉化為鏈表
while (sum > 0 || sign == 0) {
int tmp = sum % 10;
sum = sum / 10;
tmpHead.next = new ListNode(tmp);
tmpHead = tmpHead.next;
sign++;
}
return newHead.next;
}
}
簡直輕松加愉快,讓我們來提交一下。
怎么肥四,小老弟,翻車了啊。讓我們看看錯誤原因:
輸入:
[9]
[1,9,9,9,9,9,9,9,9,9]
輸出:
[0]
預期:
[0,0,0,0,0,0,0,0,0,0,1]
看樣子應該是整數型溢出了。。。難不倒我,改成long型不就完事了。
翻車嘗試2:蝦扯蛋升級法
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head1 = l1;
ListNode head2 = l2;
long i = 0;
long j = 0;
long index = 0;
while (head1 != null) {
i += head1.val * Math.pow(10, index);
index++;
head1 = head1.next;
}
index = 0;
while (head2 != null) {
j += head2.val * Math.pow(10, index);
index++;
head2 = head2.next;
}
long sum = i + j;
ListNode newHead = new ListNode(0);
ListNode tmpHead = newHead;
int sign = 0;
while (sum > 0 || sign == 0) {
int tmp = (int)(sum % 10);
sum = sum / 10;
tmpHead.next = new ListNode(tmp);
tmpHead = tmpHead.next;
sign++;
}
return newHead.next;
}
}
這次總沒事了吧,再提交一下:
這個磨人的小妖精,整出個這么大的數來折騰我,long型也溢出了。。。
逼我用絕招,是時候祭出我的BigInteger
了。
翻車嘗試3:蝦扯蛋終極法
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head1 = l1;
ListNode head2 = l2;
BigInteger i = new BigInteger(0);
BigInteger j = new BigInteger(0);
long index = 0;
while (head1 != null) {
i.add(BigInteger.valueOf(head1.val * Math.pow(10, index)));
index++;
head1 = head1.next;
}
index = 0;
while (head2 != null) {
j.add(BigInteger.valueOf(head2.val * Math.pow(10, index)));
index++;
head2 = head2.next;
}
BigInteger sum = i.add(j);
ListNode newHead = new ListNode(0);
ListNode tmpHead = newHead;
int sign = 0;
while (sum.compareTo(0) == 1 || sign == 0) {
int tmp = sum.mod(10).intValue();
sum = sum.divide(10);
tmpHead.next = new ListNode(tmp);
tmpHead = tmpHead.next;
sign++;
}
return newHead.next;
}
}
這次,連編譯都不通過了,emmmm,看來不准用BigInteger
這個類。
常規解法
既然邪門歪道走不通,那就還是用常規操作來解決吧,仔細想想,其實也很簡單,我們從兩個鏈表的頭節點開始,一起遍歷,將相加得到的結果存入新的鏈表中即可。
這里需要注意的就是要考慮進位的情況,比如:4 + 6 = 10
,那么在處理后一個節點3 + 4
的時候,需要再加1,因此需要有一個進位標志來表示是否需要進位。
另外,兩個鏈表的長度並不一定相等,需要考慮像上面那樣一個很長,一個很短,而且后續一直進位的情況:
[9]
[1,9,9,9,9,9,9,9,9,9]
所以我們可以定義一個叫carry
的變量來表示是否需要進位。
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head1 = l1;
ListNode head2 = l2;
ListNode newHead = new ListNode(0);
ListNode head3 = newHead;
// 進位標志
boolean carry = false;
while (head1 != null || head2 != null) {
// 獲取對應位置的值然后相加
int x = (head1 != null) ? head1.val : 0;
int y = (head2 != null) ? head2.val : 0;
int sum = carry ? (x + y + 1) : (x + y);
// 處理進位
if (sum >= 10){
sum -= 10;
carry = true;
} else {
carry = false;
}
// 新增節點
head3.next = new ListNode(sum % 10);
head3 = head3.next;
if (head1 != null) head1 = head1.next;
if (head2 != null) head2 = head2.next;
}
if (carry) {
head3.next = new ListNode(1);
}
return newHead.next;
}
}
嗯,這下就沒什么問題了。😜
如果你有更好的解法,歡迎留言討論~