返回
逐层深入,巧解 LeetCode 773:滑动谜题
前端
2024-01-31 09:01:19
问题
在一个 2 x 3 的板上(board)有 5 块砖瓦,用数字 1~5 来表示, 以及一块空缺用 0 来表示. 一次移动定义为选择 0 与一个相邻的数字(上下左右)进行交换. 最终当板 board 的数字排布与目标数字排布 target 完全相同时,称之为求解成功.
给定一个初始排布的 board 和一个目标排布的 target,请你求出最少交换次数,以使 board 最终排布与 target 完全相同. 如果无法求解成功,则返回 -1.
解题思路
本题的解题思路是使用深度优先搜索(DFS)算法. DFS 是一种以深度优先的方式遍历状态空间树的算法. 在 DFS 中, 我们从某个初始状态开始, 然后逐层深入地探索所有可能的下一个状态, 直到找到目标状态或穷举所有可能的状态.
在 LeetCode 773 这道题中, 我们可以将 board 的排布看成一个状态, 然后根据 board 的当前排布, 将其所有可能的下一个排布都生成出来. 这样, 我们就可以构建一个状态空间树. 然后, 我们从初始状态开始, 使用 DFS 算法逐层深入地探索状态空间树, 直到找到目标状态或穷举所有可能的状态.
算法实现
def sliding_puzzle(board, target):
"""
:type board: List[List[int]]
:type target: List[List[int]]
:rtype: int
"""
# 将 board 和 target 转换为一维列表
board_1d = [num for row in board for num in row]
target_1d = [num for row in target for num in row]
# 检查 board 和 target 是否具有相同的状态空间
if sorted(board_1d) != sorted(target_1d):
return -1
# 定义 DFS 函数
def dfs(current_state, step):
# 将 current_state 转换为二维列表
current_board = [[num for num in row] for row in current_state]
# 检查 current_board 是否与 target 相同
if current_board == target:
return step
# 寻找空缺位置
zero_index = current_state.index(0)
# 根据空缺位置生成所有可能的下一个状态
next_states = []
if zero_index % 3 > 0:
next_states.append(swap(current_state, zero_index, zero_index - 1))
if zero_index % 3 < 2:
next_states.append(swap(current_state, zero_index, zero_index + 1))
if zero_index > 2:
next_states.append(swap(current_state, zero_index, zero_index - 3))
if zero_index < 6:
next_states.append(swap(current_state, zero_index, zero_index + 3))
# 递归地探索所有可能的下一个状态
min_step = float('inf')
for next_state in next_states:
if next_state not in visited:
visited.add(next_state)
step += 1
next_step = dfs(next_state, step)
if next_step != -1:
min_step = min(min_step, next_step)
step -= 1
visited.remove(next_state)
# 返回最小交换次数
return min_step if min_step != float('inf') else -1
# 定义交换函数
def swap(state, index1, index2):
state[index1], state[index2] = state[index2], state[index1]
return state
# 初始化 visited 集合,用于记录已访问过的状态
visited = set()
# 从初始状态开始搜索
result = dfs(board_1d, 0)
return result
复杂度分析
- 时间复杂度:本题的 DFS 算法的时间复杂度为 O(m^n), 其中 m 为状态空间的大小, n 为最长路径的长度. 在本题中, m = 5!, n = 12, 因此时间复杂度为 O(5! * 12).
- 空间复杂度:本题的 DFS 算法的空间复杂度为 O(m + n), 其中 m 为状态空间的大小, n 为最长路径的长度. 在本题中, m = 5!, n = 12, 因此空间复杂度为 O(5! + 12).