連結リストのつなぎ先を付け替えて逆順にする

連結リストの先頭を受け取り、節の並びを逆にしたリストの先頭を返します。前、いま、次の 3 つを指で持ち、つなぎ先を 1 つずつ後ろ向きに付け替える練習です。

海外で定番の問題リスト 4 本のうち 3 本に入っています (Blind 75、NeetCode 150、Grind 75)

問題

連結リストの先頭の節 head を受け取ります。節の並びを逆にしたリストを作り、その先頭の節を返す関数を書いてください。

  • 各節は val (値) と next (次の節) を持ちます。最後の節の next は、Python では None、JavaScript では null、Go では nil です。Go の節は ListNode で、Val、Next と大文字で始まります
  • 新しい節は作らず、今ある節のつなぎ先を付け替えて逆にしてください
  • リストが空 (head が無い) のときは、空のまま返します
  • 節の数は 0 以上 5000 以下、値はどれも -5000 以上 5000 以下です

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

入力と出力の例

例 1

head = [3, 8, 1, 5]
[5, 1, 8, 3]

例 2

節が 1 つなら、そのまま返ります。

head = [9]
[9]

例 3

空のリストです。

head = []
[]

面接での聞かれ方

連結リストの問題の入口として、とてもよく出ます。問題文は短く渡されます。

  • 「単方向の連結リストを逆順にしてください」
  • 書き終えたあとに「再帰でも書けますか?」と聞かれることが多いです。書けることに加えて、深いリストで再帰の段が増えすぎる弱さも言えると評価が上がります
  • 「位置 m から n までだけを逆にできますか?」と、一部だけ逆にする続きが来ることもあります

ジュニアの問題なので、つなぎ先を付け替える順番を、図を描かずに口で説明できるかが見られます。

ヒント

まだ開いていません

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

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

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

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

main.py
def reverse_list(head: 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(reverse_list(build_list([3, 8, 1, 5]))))

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