Leetcode『2.両数加算』のJS実現
4220 ワード
面接の準備をして、臨時に仏足を抱いてleetcodeを塗り始め、ついでにjavascriptを練習して、過程をブログに記録することにしました.主に個人的な問題をまとめて、みんなは見なくてもいいです.
題目《2.両数加算》
2つの非負の整数を表すために、2つの非空のチェーンテーブルが与えられる.ここで、それぞれのビット数は逆順序で格納され、各ノードには1桁の数字しか格納されません.
この2つの数を加算すると、新しいチェーンテーブルが返され、合計が表示されます.
数値0以外の2つの数は0で始まると仮定できます.
例:
上手になると料理が多いと感じて、バグに向かってプログラミングして十数二十回提出しました.これは私が初めて通過したバージョンで、長くて臭い実現です.
私の考えは公式の考えと比較しています.
1.最初に結果を生成するノード.公式では、ループ内のコードを多重化できるように、ダミーノードを先頭に使用しています.最初は最初のノードが位置を上げる可能性があるとは考えていませんでしたが、後で追加しました.
2.無限ループ内では、常に2つのチェーンテーブルの対応値とcarryビットを加算し、10未満か10以上かを判断し、新しいノードとcarryの値を状況別に処理する.ここでは公式にsum/10(Javaのintから自動的に下向きになるので、JSではMath.floorで手動にしましょう)とsum mod 10を使うと、操作が簡略化されifは不要です
3.いずれかのチェーンが終端したら、残りのすべてを結果チェーンテーブルの後ろに追加し、breakします.実は最初にこのように書いたとき、私はキャリー(9999+1が発生する場合)を考慮していなかったので、長いコードを書いて補いました.実際には1本のチェーンが終わり、後ろのものを0にすればいいだけで、計算ロジックは元の状況と同じで、わざわざ書き直す必要はありません.l 1とl 2が両端に着いたら終わりです.
公式の答えの偽コードは以下の通りです.は、現在のノードを、リストを返すダミーノードに初期化する. は、キャリーキャリーを0に初期化する. は、pおよびqをそれぞれリストl 1およびl 2のヘッダに初期化する. リストl 1およびl 2は、それらの末端に達するまで巡回する. xをノードppの値に設定します.ppがl 1の末尾に達した場合、その値は0に設定される. yをノードqの値とする.qがl 2の末尾に達した場合、その値は0に設定される. sum=x+y+carryを設定します. キャリー値、carry=sum/10を更新します. は、(sum mod 10)という数値の新しいノードを作成し、現在のノードの次のノードに設定し、現在のノードを次のノードに進みます. 同時に、pとqを次のノードに進む.
carry=1が成立しているかどうかをチェックし、成立している場合は、戻りリストに数字1を含む新しいノードを追加します. は、ダミーノードの次のノードを返す.
公式の考え方で書かれたコードは、元の20%にすぎません.
題目《2.両数加算》
2つの非負の整数を表すために、2つの非空のチェーンテーブルが与えられる.ここで、それぞれのビット数は逆順序で格納され、各ノードには1桁の数字しか格納されません.
この2つの数を加算すると、新しいチェーンテーブルが返され、合計が表示されます.
数値0以外の2つの数は0で始まると仮定できます.
例:
:(2 -> 4 -> 3) + (5 -> 6 -> 4)
:7 -> 0 -> 8
:342 + 465 = 807
上手になると料理が多いと感じて、バグに向かってプログラミングして十数二十回提出しました.これは私が初めて通過したバージョンで、長くて臭い実現です.
var addTwoNumbers = function(l1, l2) {
let carry = 0;
let startNode;
if (l1.val + l2.val < 10){
startNode = new ListNode(l1.val + l2.val);
}else{
startNode = new ListNode(l1.val + l2.val - 10);
carry = 1;
}
let node = startNode;
while (true){
if (l1.next === null){
while (l2.next !== null){
l2 = l2.next;
if (l2.val + carry < 10){
node.next = new ListNode(l2.val + carry);
carry = 0;
} else{
node.next = new ListNode(l2.val + carry - 10)
carry = 1;
}
node = node.next;
}
if (carry === 1){
node.next = new ListNode(1);
}
break;
}
if (l2.next === null){
while (l1.next !== null){
l1 = l1.next;
if (l1.val + carry < 10){
node.next = new ListNode(l1.val + carry);
carry = 0;
} else{
node.next = new ListNode(l1.val + carry - 10)
carry = 1;
}
node = node.next;
}
if (carry === 1){
node.next = new ListNode(1);
}
break;
}
l1 = l1.next;
l2 = l2.next;
if (l1.val + l2.val + carry < 10){
node.next = new ListNode(l1.val + l2.val + carry);
carry = 0;
} else {
node.next = new ListNode(l1.val + l2.val + carry - 10);
carry = 1;
}
node=node.next;
}
return startNode;
};
私の考えは公式の考えと比較しています.
1.最初に結果を生成するノード.公式では、ループ内のコードを多重化できるように、ダミーノードを先頭に使用しています.最初は最初のノードが位置を上げる可能性があるとは考えていませんでしたが、後で追加しました.
2.無限ループ内では、常に2つのチェーンテーブルの対応値とcarryビットを加算し、10未満か10以上かを判断し、新しいノードとcarryの値を状況別に処理する.ここでは公式にsum/10(Javaのintから自動的に下向きになるので、JSではMath.floorで手動にしましょう)とsum mod 10を使うと、操作が簡略化されifは不要です
3.いずれかのチェーンが終端したら、残りのすべてを結果チェーンテーブルの後ろに追加し、breakします.実は最初にこのように書いたとき、私はキャリー(9999+1が発生する場合)を考慮していなかったので、長いコードを書いて補いました.実際には1本のチェーンが終わり、後ろのものを0にすればいいだけで、計算ロジックは元の状況と同じで、わざわざ書き直す必要はありません.l 1とl 2が両端に着いたら終わりです.
公式の答えの偽コードは以下の通りです.
公式の考え方で書かれたコードは、元の20%にすぎません.
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var addTwoNumbers = function(l1, l2) {
let dummyHead = new ListNode(0);
let p = l1, q = l2, curr = dummyHead;
let carry = 0;
while (p || q){
let x = p ? p.val : 0;
let y = q ? q.val : 0;
let sum = x + y + carry;
carry = sum < 10 ? 0 : 1;
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p){
p = p.next;
}
if (q){
q = q.next;
}
}
if (carry > 0){
curr.next = new ListNode(carry);
}
return dummyHead.next;
};