対象アルゴリズム:Stable Partition via Two Dummy Lists(Pure / Non-destructive)

Partition List を徹底解説(Python / 可視化 / インタラクティブ)

連結リストをしきい値 x安定 に 2 分割。番兵(ダミー)ノードと テール参照で実装をシンプルにし、相対順序を維持します。

1. アルゴリズム概要

単方向連結リスト head を 1 回だけ走査し、値が < x のノードを less、それ以外を ge に 末尾追加(安定)。最後に less の末尾を ge の先頭へ連結します。

2. ステップバイステップ解説(視覚化付き)

  1. 1

    Init dummies & tails

    空の less / ge を作成

  2. 2

    Single pass

    cur を進めて分配を判断

  3. 3

    Append to less (< x)

    1, 2, 2 が less に入る

  4. 4

    Append to ge (≥ x)

    4, 3, 5 が ge に入る

  5. 5

    Connect lists

    less → ge

入力: [1, 4, 3, 2, 5, 2], x = 3

ステップをクリック / Play でアニメーション
Input 1 4 3 2 5 2

初期化:番兵(lessDummy / geDummy)とテール参照を用意。

3. コード例(Python / LeetCode形式)

from __future__ import annotations
from typing import Optional, TYPE_CHECKING

# Type-checking fallback (LeetCode env already provides ListNode)
if TYPE_CHECKING:
    class ListNode:
        def __init__(self, val: int = 0, next: Optional["ListNode"] = None) -> None: ...
        val: int
        next: Optional["ListNode"]

try:
    ListNode  # type: ignore[name-defined]
except NameError:
    class ListNode:
        __slots__ = ("val", "next")
        def __init__(self, val: int = 0, next: Optional["ListNode"] = None) -> None:
            self.val = val
            self.next = next

class Solution:
    def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
        """Stable partition of linked list around x (pure, non-destructive)."""
        # 1) create dummies and tails
        less_dummy = ListNode(0)
        ge_dummy = ListNode(0)
        lt_tail = less_dummy
        ge_tail = ge_dummy

        # 2) single pass: append new nodes
        cur = head
        while cur is not None:
            v = cur.val
            if v < x:
                lt_tail.next = ListNode(v)
                lt_tail = lt_tail.next
            else:
                ge_tail.next = ListNode(v)
                ge_tail = ge_tail.next
            cur = cur.next

        # 3) connect less -> ge
        lt_tail.next = ge_dummy.next
        ge_tail.next = None
        return less_dummy.next

4. 視覚的図解・フローチャート

Input 1 4 3 2 5 2 Build less (< x) 1 2 2 Build ge (≥ x) 4 3 5

5. 時間計算量

Time

O(n)

各ノードは 1 回だけ処理。

Space(本実装 / Pure)

O(n)

入力不変のため新ノードを構築。

Space(参考 in-place)

O(1)

破壊的再配線なら追加メモリは定数。