↓快轉到主要內容
  1. LeetCode/

LeetCode 773: Sliding Puzzle

·1 分鐘· ·
LeetCode Hard Breadth-First-Search Dynamic-Programming Memoization Matrix
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-09-07

  • 提交紀錄:Accepted(一次通過)

解題思路
#

2 × 3 的盤面只有 6! = 720 種排列,可以把整個盤面當成一個狀態做 BFS,第一次走到目標的步數就是最少步數(見 BFS 的狀態空間 BFS)。

  • 狀態:把盤面攤平成長度 6 的字串,例如 "412503"。
  • 轉移:找到 0 的位置,跟相鄰的格子交換。攤平後每個位置的鄰居是固定的,先寫成表:
0 1 2
3 4 5

0: [1, 3]、1: [0, 2, 4]、2: [1, 5]、3: [0, 4]、4: [1, 3, 5]、5: [2, 4]。

BFS 結束都沒碰到 "123450" 就回傳 -1。

我的解法
#

from collections import deque

class Solution:
    def slidingPuzzle(self, board: List[List[int]]) -> int:
        start = "".join(str(x) for row in board for x in row)
        target = "123450"
        neighbors = {0: [1, 3], 1: [0, 2, 4], 2: [1, 5], 3: [0, 4], 4: [1, 3, 5], 5: [2, 4]}

        queue = deque([(start, 0)])
        seen = {start}
        while queue:
            state, moves = queue.popleft()
            if state == target:
                return moves
            z = state.index("0")
            for nb in neighbors[z]:
                s = list(state)
                s[z], s[nb] = s[nb], s[z]
                nxt = "".join(s)
                if nxt not in seen:
                    seen.add(nxt)
                    queue.append((nxt, moves + 1))
        return -1

複雜度
#

最多 720 個狀態,每個最多 3 個鄰居,常數時間。

要特別避免的錯誤
#

  • 用 list 當狀態:list 不能放進 set,要轉成字串或 tuple。
  • 攤平後左右的鄰居要注意換行:位置 2 和位置 3 不相鄰。

面試口說整理
#

盤面只有 720 種,所以我把整個盤面攤平成字串當 BFS 的狀態,每一步把 0 跟相鄰的格子交換,用 seen 去重,第一次走到目標就是最少步數,走不到就回傳 -1。鄰居關係先寫成表,避免攤平後誤把換行的兩格當成相鄰。

相關文章

LeetCode 2328: Number of Increasing Paths in a Grid
·2 分鐘
LeetCode Hard Dynamic-Programming Grid-Dp Memoization Topological-Sort Matrix
LeetCode 2328 解題筆記:嚴格遞增所以沒有環;dp[cell] = 1 + Σ dp[比它大的鄰居],依值由大到小處理(或記憶化 DFS),全部加起來
LeetCode 488: Zuma Game
·2 分鐘
LeetCode Hard Dynamic-Programming Memoization Breadth-First-Search String Stack
LeetCode 488 解題筆記:board 最多 16 顆、hand 最多 5 顆,把 (board, hand) 整個當狀態做 DFS + 記憶化;只在「同色球前面」和「拆開兩顆同色球」兩種位置插入
LeetCode 4041: Minimum Operations to Form Subset Sum II
·2 分鐘
LeetCode Hard Dynamic-Programming Knapsack Breadth-First-Search Array
LeetCode 4041 解題筆記:乘除可以任意順序,用 BFS 找每個數能變成的所有值(不超過 sum)和最少步數,再做跟 4040 一樣的分組 0/1 背包
LeetCode 3989: Maximum Consistent Columns in a Grid
·1 分鐘
LeetCode Hard Dynamic-Programming Matrix Array
LeetCode 3989 解題筆記:保留的欄位是一個子序列,只要相鄰的兩欄相容;LIS 型 DP,dp[j] = 以第 j 欄結尾的最長合法序列
LeetCode 3651: Minimum Cost Path with Teleportations
·2 分鐘
LeetCode Hard Dynamic-Programming Grid-Dp Matrix Array
LeetCode 3651 解題筆記:一層一層算傳送次數;傳送到某格的成本是上一層「值 >= 它的格子」的最小值,排序後用前綴最小值求,再跑一次右 / 下的 Grid DP
LeetCode 2163: Minimum Difference in Sums After Removal of Elements
·2 分鐘
LeetCode Hard Dynamic-Programming Heap Array
LeetCode 2163 解題筆記:枚舉第一段和第二段的分界 k;左邊 nums[:k] 選 n 個最小的(最大堆維護),右邊 nums[k:] 選 n 個最大的(最小堆維護),前後綴各掃一次