时间复杂度:O(mn),空间复杂度:O(1)
解题思路
一开始想用回溯法做,又想用动态规划做,看了题解发现这题用动态规划做真是太太太太太简单了……
看了两遍官方题解的动图,不看文字就明白了意思。
dp二维数组用来保存从起点到该点的最小路径和,所以我们要按照动态规划的常规思路确定边界。
这道题的边界便是起点所在的行和列,起点所在行的dp从左到右累加即可,起点所在列的dp从上到下累加即可,而除掉边界部分的dp值则由其左和上较小的dp值决定。这样我们通过遍历起点所在行、遍历起点所在列最后遍历中间部分即可确定最小路径和。
此外,该题目可以原地修改二维数组不用另外开辟内存空间来保存dp,这样空间复杂度能从O(mn)或者O(n)优化为O(0),因为对于我们来说遍历整个二维数组一次就可以得到答案了。
AC代码
func minPathSum(grid [][]int) int {
m,n:=len(grid),len(grid[0])//m行n列
for x:=1;x<n;x++{
grid[0][x]+=grid[0][x-1]
}
for y:=1;y<m;y++{
grid[y][0]+=grid[y-1][0]
}
for y:=1;y<m;y++{
for x:=1;x<n;x++{
grid[y][x]+=min(grid[y][x-1],grid[y-1][x])
}
}
return grid[m-1][n-1]
}
func min(x,y int)int{
if x<y{
return x
}
return y
}
由于是起点到终点,我更喜欢把二维数组看成坐标轴,横向是x轴纵向是y周,所以代码看起来比用i和j变量的代码别扭……
感悟
刷题还是太少了,动态规划思想一定要烂熟于心呀!