連結リストの中間ノードを削除する

単方向連結リストから中間ノードを削除する必要があります。中間ノードは、0ベースのインデックスを使用して ⌊n / 2⌋ 番目のノードとします。

効率的な解決方法は以下の通りです。

戦略

2つのポインタを使用して、1回の走査で中間を見つけます。

ロジック

  1. エッジケースを処理します。リストにノードが1つしかない場合は、null を返します。
  2. スローポインタとファストポインタを head に初期化します。
  3. ファストポインタを2ステップ、スローポインタを1ステップ進めます。
  4. スローポインタの1つ後ろを維持するように prev ポインタを更新します。
  5. ループが終了したら、prev ノードを slow の次のノードにリンクします。これにより、中間ノードがスキップされます。

計算量

PHPによる実装

function deleteMiddle(ListNode $head): ?ListNode
{
    if ($head->next == null) {
        return null;
    }

    $slow = $head;
    $fast = $head;
    $prev = null;

    while ($fast !== null && $fast->next !== null) {
        $prev = $slow;
        $slow = $slow->next;
        $fast = $fast->next->next;
    }

    $prev->next = $slow->next;

    return $head;
}

出典: https://dev.to/mdarifulhaque/2095-delete-the-middle-node-of-a-linked-list-4jf1