引言:用Js攻略leetcode中的算法吟孙,將會(huì)介紹自己的思路和注意點(diǎn),一邊學(xué)習(xí)一邊愉快刷題呀。
問(wèn)題1:
給定兩個(gè)非空鏈表來(lái)表示兩個(gè)非負(fù)整數(shù)帚称。位數(shù)按照逆序方式存儲(chǔ),它們的每個(gè)節(jié)點(diǎn)只存儲(chǔ)單個(gè)數(shù)字秽澳。將兩數(shù)相加返回一個(gè)新的鏈表世杀。
你可以假設(shè)除了數(shù)字 0 之外,這兩個(gè)數(shù)字都不會(huì)以零開(kāi)頭肝集。
示例:
輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807
思考:
- 342 + 465 = 807 也就是位位相加瞻坝,注意一下每一位相加要加上進(jìn)位,最后一次兩個(gè)鏈表都到了結(jié)束,也要注意一下有沒(méi)有進(jìn)位:比如 99 + 1 = 100;
- 注意鏈表怎么把每個(gè)節(jié)點(diǎn)連接起來(lái):每次生成一個(gè)listnode元素,通過(guò)當(dāng)前l(fā)istnode的下一個(gè)元素(cur_node.next)連城鏈所刀。
- 最后返回一個(gè)列表衙荐,所以要給個(gè)頭(result)指示列表起始的位置,再通過(guò)cur_node鏈接起鏈表串
代碼:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
var addTwoNumbers = function(l1, l2) {
var val1 = 0;
var val2 = 0;
var carry = 0;//進(jìn)位
var result = null;//返回值
var cur_node = null;
var sumWithCarry = function(sum) {
if(sum >= 10) {
carry = 1;
sum = sum - 10;
} else {
carry = 0;
}
return sum;
}
if(l1 || l2) {
val1 = l1 ? l1.val : 0;
val2 = l2 ? l2.val : 0;
l1 = l1 ? l1.next : null;
l2 = l2 ? l2.next : null;
cur_node = new ListNode(sumWithCarry(val1 + val2));
result = cur_node;
while(l1 || l2) {
val1 = l1 ? l1.val : 0;
val2 = l2 ? l2.val : 0;
l1 = l1 ? l1.next : null;
l2 = l2 ? l2.next : null;
cur_node.next = new ListNode(sumWithCarry(val1 + val2 + carry));
cur_node = cur_node.next;
}
if(carry != 0) {
cur_node.next = new ListNode(sumWithCarry(carry));
}
}
return result;
};
問(wèn)題2:
如果鏈表中的數(shù)字不是按逆序存儲(chǔ)的呢浮创?例如:
(3 -> 4 -> 2) + (4 -> 6 -> 5) = 8 -> 0 -> 7
符合人類觀察的習(xí)慣: 342+465 = 807
思路:
- 思路1也是位位相加, 將兩個(gè)列表中的值存入數(shù)組中:result_array = [3+4, 4+6, 2+5] = [7,10, 7], 再考慮進(jìn)位為題變成 [ 8, 0, 7 ], 最后生成listnode連接起來(lái)忧吟。但是這種方法在列表不等長(zhǎng)的情況下是不可行了,可跳過(guò)去看最后斩披。
var addTwoNumbers = function(l1, l2) {
var result_array = [];
var result = null;//返回值
var cur_node = null;
var val1 = 0;
var val2 = 0;
while(l1 || l2) {
val1 = l1 ? l1.val : 0;
val2 = l2 ? l2.val : 0;
l1 = l1 ? l1.next : null;
l2 = l2 ? l2.next : null;
result_array.push(val1 + val2)
}
for (var i = result_array.length - 1; i >= 0; i--) {
if(result_array[i] >= 10) {
result_array[i] = result_array[i] - 10;
if(i > 0) {
result_array[i -1] = result_array[i-1] + 1;
} else {
result_array.unshift(1);
return;
}
}
}
if( result_array.length ){
result = new ListNode(result_array[0]);
cur_node = result;
if(result_array.length > 1) {
for (var i = 1; i <= result_array.length - 1; i ++) {
cur_node.next = new ListNode(result_array[i]);
cur_node = cur_node.next;
}
}
}
return result;
};
乍看起來(lái)非常完美溜族,但是遇到了一個(gè)極其重要的邏輯問(wèn)題:在處理兩列表等長(zhǎng)時(shí)這個(gè)方法可行,但是不等長(zhǎng)時(shí)相加錯(cuò)誤垦沉,比如: [9,9] + [2] = [9, 11]=[1,0,1], 但上述辦法算出來(lái)是[11,9]=[1,1,9],所以在兩列表不等長(zhǎng)時(shí)煌抒,必須將相加位位置對(duì)齊,在另一個(gè)列表元素?cái)?shù)組前面加上很多0厕倍;但是我覺(jué)得這種方式時(shí)間復(fù)雜度太高了寡壮。
- 思路2:然后我想為什么不能將它們變?yōu)閿?shù)字再進(jìn)行相加呢?[9,9] + [2] = 99 + 2 = 101 = [1,0,1]
代碼:
var addTwoNumbers = function(l1, l2) {
var result_array = [];
var result_sum = 0;
var result1 = 0;
var result2 = 0;
var result = null;//返回值
var cur_node = null;
var val1 = 0;
var val2 = 0;
while(l1 || l2) {
val1 = l1 ? l1.val : 0;
l1 = l1 ? l1.next : null;
result1 = val1 + result1*10;
val2 = l2 ? l2.val : 0;
l2 = l2 ? l2.next : null;
result2 = val2 + result2*10;
}
result_sum = result1 + result2;
while(result_sum >= 10) {
result_array.push(result_sum % 10);
result_sum = ~~(result_sum / 10);
}
result_array.push(result_sum);
if( result_array.length ){
for (var i = result_array.length - 1; i >= 0; i--) {
if(i == result_array.length - 1) {
result = new ListNode(result_array[i]);
cur_node = result;
} else {
cur_node.next = new ListNode(result_array[i]);
cur_node = cur_node.next;
}
}
}
return result;
};