diff --git a/source/_posts/算法/动态规划(1).md b/source/_posts/算法/动态规划(1).md index c926097..2d7eb1a 100644 --- a/source/_posts/算法/动态规划(1).md +++ b/source/_posts/算法/动态规划(1).md @@ -84,7 +84,7 @@ public int uniquePaths(int m, int n) { return 0; } int[][] nums = new int[m+1][n+1]; - nums[1][1] = 1; + nums[1][1] = 1; // 起点方格的走法 for(int i=1 ; i<=m ; i++) { for(int j=1 ; j<=n ; j++) { if(i==1 && j==1) { @@ -97,4 +97,51 @@ public int uniquePaths(int m, int n) { } ``` 整体思路就是创建一个整数二维数组, m+1和n+1是为了留出第一行和第一列数值都是0 -方便进行计算, 当然这个也不是必须的, 在循环当中判断也可以, 但是不影响时间和空间复杂度 \ No newline at end of file +方便进行计算, 当然这个也不是必须的, 在循环当中判断也可以, 但是不影响时间和空间复杂度 +时间复杂度`O(mn)` +空间复杂度`O(mn)` + +#### 进阶 +如果某些方格存在障碍物, 机器人不能经过这些格子 +有多少走法该如何计算 +传入的参数是一个整数二维数组, 其中0代表该位置无障碍, 1代表该位置有障碍 + +这个问题同样可以沿用上一题的解法 +需要补充的就是在障碍物的位置, 右侧和下方的格子 +其对应的来自左侧和上面的走法应该是0, 因为无法从障碍物走过来 + +代码实现 +```java +public int uniquePathsWithObstacles(int[][] obstacleGrid) { + int m = obstacleGrid.length; + if(m == 0) { + return 0; + } + int n = obstacleGrid[0].length; + // 需要排除宽度是0以及高度是0的情况, 这种情况下走法是0 + // 还需要排除起点位置有障碍和终点位置有障碍的情况, 这种情况下走法也是0 + if(n == 0 || obstacleGrid[0][0] == 1 || obstacleGrid[m-1][n-1] == 1) { + return 0; + } + int[][] nums = new int[m+1][n+1]; + nums[1][1] = 1; + for(int i=1 ; i<=m ; i++) { + for(int j=1 ; j<=n ; j++) { + if(i == 1 && j == 1) { + continue; + } + // 判断左侧是否有障碍 + int left = (i > 1 && obstacleGrid[i-2][j-1] == 0) ? nums[i-1][j] : 0; + // 判断上方是否有障碍 + int top = (j > 1 && obstacleGrid[i-1][j-2] == 0) ? nums[i][j-1] : 0; + nums[i][j] = left + top; + } + } + return nums[m][n]; +} +``` + +### 总结 +动态规划的主要应用于使用穷举去解决时间复杂度过高的问题 +将大问题化解为小问题, 并且记住前面小问题的求解结果, 避免在穷举过程中对前面小问题的重复求解 +从而降低时间复杂度 \ No newline at end of file diff --git a/source/_posts/算法/动态规划(2).md b/source/_posts/算法/动态规划(2).md new file mode 100644 index 0000000..3266889 --- /dev/null +++ b/source/_posts/算法/动态规划(2).md @@ -0,0 +1,94 @@ +--- +title: 动态规划(2) +date: 2018-9-1 21:40:02 +tags: + - 算法 + - 动态规划 +categories: + - 算法 +--- +### 最小路径和 + +给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 +说明:每次只能向下或者向右移动一步。 + +> 示例: +输入: +[ + [1,3,1], + [1,5,1], + [4,2,1] +] +输出: 7 +解释: 因为路径 1→3→1→1→1 的总和最小。 + +这个问题其实和上一篇当中的 **最大子序和** 可以采用相似的方式来解决 +创建一个 m x n 的二维数组 +数组中每个位置记录到达该位置的最小路径和 +到达该位置的最小路径和 = min(到达左侧位置的最小路径和, 到达上方位置的最小路径和) + 给定数组在当前格的值 +同时排除掉第一行和第一列的特殊情况 + +#### 代码实现 +```java +public int minPathSum(int[][] grid) { + int m = grid.length; + if(m == 0) { + return 0; + } + int n = grid[0].length; + if(n == 0) { + return 0; + } + int[][] nums = new int[m][n]; + nums[0][0] = grid[0][0]; + int currentMin = 0; + for(int i=0 ; i