📅  最后修改于: 2023-12-03 15:10:47.102000             🧑  作者: Mango
在矩阵操作中,经常需要查找从矩阵起点到达末尾的最低步数,本套装提供多种算法解决该问题。
使用动态规划,设$dp[i][j]$表示从起点矩阵[0][0]到达当前位置[i][j]所需的步数。则状态转移方程为:
$$dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j]$$
其中$grid[i][j]$表示矩阵当前位置的值。
算法1代码:
def minPathSum(grid):
m,n = len(grid),len(grid[0])
dp = [[0] * n for _ in range(m)]
dp[0][0] = grid[0][0]
for i in range(1,m):
dp[i][0] = dp[i-1][0] + grid[i][0]
for j in range(1,n):
dp[0][j] = dp[0][j-1] + grid[0][j]
for i in range(1,m):
for j in range(1,n):
dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + grid[i][j]
return dp[-1][-1]
时间复杂度:$O(mn)$
使用深度优先搜索,逐步遍历矩阵,记录当前步数。若当前步数+到终点的距离大于已知最小步数,则停止搜索。若能到达终点,则更新最小步数。
算法2代码:
def minPathSum(grid):
m,n = len(grid),len(grid[0])
res = float('inf')
def dfs(i,j,step):
nonlocal res
if step+grid[i][j]>res: # 剪枝
return
if i == m-1 and j == n-1:
res = min(res,step+grid[i][j])
return
if i<m-1:
dfs(i+1,j,step+grid[i][j])
if j<n-1:
dfs(i,j+1,step+grid[i][j])
dfs(0,0,0)
return res
时间复杂度:$O(2^{m+n})$
使用广度优先搜索,逐步遍历矩阵每一格,拓展下一步的可达位置,记录当前步数。若到达终点,则更新最小步数。
算法3代码:
import queue
def minPathSum(grid):
m,n = len(grid),len(grid[0])
q = queue.Queue()
q.put((0,0,0))
while not q.empty():
i,j,step = q.get()
if i == m-1 and j == n-1:
return step+grid[i][j]
if i<m-1:
q.put((i+1,j,step+grid[i][j]))
if j<n-1:
q.put((i,j+1,step+grid[i][j]))
return -1
时间复杂度:$O(mn)$
对于本问题,使用动态规划算法1效率最高,时间复杂度为O(mn),是常规算法之中最优解。而深度优先搜索和广度优先搜索虽然时间复杂度较高,但对于一些复杂矩阵场景,搜索算法可以获得最优解。