間をあけた 2 本の指で連結リストの後ろから n 番目の節を外す

連結リストの後ろから数えて n 番目の節を外し、先頭を返します。n 歩先に出した指と一緒に進め、1 回なめるだけで外す節の 1 つ前を見つける練習です。

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

問題

連結リストの先頭 head と整数 n を受け取ります。後ろから数えて n 番目の節をリストから外し、残ったリストの先頭の節を返す関数を書いてください。

  • 後ろから 1 番目は最後の節です
  • n は 1 以上、節の数以下です
  • 各節は val (値) と next (次の節) を持ちます。最後の節の next は、Python では None、JavaScript では null、Go では nil です。Go の節は ListNode で、Val、Next と大文字で始まります
  • 先頭の節を外すこともあります。節が 1 つで、それを外すと空のリストになります
  • 節の数は 1 以上 30 以下、値はどれも 0 以上 100 以下です
  • リストを 1 回なめるだけで解いてください

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

入力と出力の例

例 1

待ち行列の後ろから 2 番目の人が列を離れます。後ろから 2 番目は 40 です。

head = [10, 20, 30, 40, 50] n = 2
[10, 20, 30, 50]

例 2

後ろから 3 番目は、節が 3 つなら先頭です。先頭が外れて、2 番目の節が新しい先頭になります。

head = [6, 7, 8] n = 3
[7, 8]

例 3

節が 1 つだけで、それを外すと空のリストになります。

head = [42] n = 1
[]

面接での聞かれ方

連結リストの 2 本の指の使い方を見る問題として、ミドルの面接でよく出ます。

  • 「連結リストの後ろから n 番目の節を消してください」
  • 長さを数えてから前から探す 2 回なめる書き方を答えると、「1 回で済ませられますか?」と聞かれます
  • 「先頭の節を消すときはどうなりますか?」と、端の場合を確かめられます

ミドルの問題なので、先頭を外す場合を、ダミーの節で場合分けなしに書けるかが見られます。

ヒント

まだ開いていません

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

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

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

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

main.py
def remove_nth_from_end(head: ListNode | None, n: int) -> 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(remove_nth_from_end(build_list([10, 20, 30, 40, 50]), 2)))

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