繰り上がりを持ちながら、1 の位から並んだ 2 本の連結リストの数を足す

数の桁を 1 の位から順に 1 つずつ持つ 2 本の連結リストを受け取り、2 つの数の和を同じ形の連結リストで返します。繰り上がりを持ちながら、長さの違う 2 本を同時になめる練習です。

海外で定番の問題リスト 4 本には入っていません

問題

0 以上の整数を表す 2 本の連結リストの先頭 head1 と head2 を受け取ります。2 つの数の和を、同じ形の連結リストで返す関数を書いてください。

  • 1 つの節が 1 つの桁 (0 から 9) を持ちます。先頭が 1 の位で、次が 10 の位、その次が 100 の位、と並びます。たとえば 352 は [2, 5, 3] です
  • 数が 0 のときは [0] です。それ以外で、いちばん上の桁 (リストの最後) が 0 になることはありません
  • 答えも同じ形で、先頭を 1 の位にして返します
  • 各節は val (値) と next (次の節) を持ちます。最後の節の next は、Python では None、JavaScript では null、Go では nil です。Go の節は ListNode で、Val、Next と大文字で始まります
  • それぞれの節の数は 1 以上 100 以下です。桁が 100 あるので、言語の整数に直して足すことはできません

例では、リストを先頭から読んだ値の並びで書きます。

入力と出力の例

例 1

352 と 471 を足します。1 の位は 2 + 1 = 3、10 の位は 5 + 7 = 12 で 2 を書いて 1 を繰り上げ、100 の位は 3 + 4 + 1 = 8 です。和は 823 です。

head1 = [2, 5, 3] head2 = [1, 7, 4]
[3, 2, 8]

例 2

9999 と 1 を足すと 10000 です。繰り上がりが最後まで続き、桁が 1 つ増えます。長さの違う 2 本でも足せます。

head1 = [9, 9, 9, 9] head2 = [1]
[0, 0, 0, 0, 1]

例 3

0 と 0 を足すと 0 です。

head1 = [0] head2 = [0]
[0]

面接での聞かれ方

連結リストの最初の問題としてよく出ます。ミドルの面接でも、短く確実に書けるかを見るために出されます。

  • 「桁を逆順に持つ 2 本の連結リストの和を、同じ形で返してください」
  • 「整数に直して足して、リストに戻せばよいのでは?」という答えには、「桁が 100 あったら?」と返されます。言語によっては溢れます
  • 書き終えたあとに「桁が上の位から並んでいたらどうしますか?」と続きを聞かれることがあります。そのときは両方を逆にしてから足すか、スタックに積んで後ろから足します

ミドルの問題なので、長さの違い、最後の繰り上がり、の 2 つの端を 1 つの繰り返しで扱えるかが見られます。

ヒント

まだ開いていません

付箋は 4 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

アルゴリズムのチートシートの「配列と文字列」に、この型の要点を表とコードでまとめています。

配列と文字列の問題は、全部の組を調べると手間が大きくなる所を、窓や左右の添字で減らす形が多いです。

main.py
def add_digit_lists(head1: ListNode | None, head2: ListNode | None) -> ListNode | None:
    """
    Goal: 何を返すか

    idea1: まず思いつく案
    -> runtime: O(?)  space: O(?)

    idea2: もっと速い案
    -> runtime: O(?)  space: O(?)

    edge case: 空、1 つだけ、など
    """
    # 連結リストの節は val、next を持ちます。最後の next は None です
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
# build_list は並びから連結リストを組みます
print(list_values(add_digit_lists(build_list([2, 5, 3]), build_list([1, 7, 4]))))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します