Leetcode『2.両数加算』のJS実現

4220 ワード

面接の準備をして、臨時に仏足を抱いてleetcodeを塗り始め、ついでにjavascriptを練習して、過程をブログに記録することにしました.主に個人的な問題をまとめて、みんなは見なくてもいいです.
題目《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が両端に着いたら終わりです.
 
公式の答えの偽コードは以下の通りです.
  • は、現在のノードを、リストを返すダミーノードに初期化する.
  • は、キャリーキャリーを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%にすぎません.
    /**
     * 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;
    };