什么网站类型,东莞关键词优化推广,晚上做设计挣钱的网站,网站安装教程不同路径
62. 不同路径 - 力扣#xff08;LeetCode#xff09;
一个机器人位于一个 m x n 网格的左上角 #xff08;起始点在下图中标记为 “Start” #xff09;。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角#xff08;在下图中标记为 “Finis…不同路径
62. 不同路径 - 力扣LeetCode
一个机器人位于一个 m x n 网格的左上角 起始点在下图中标记为 “Start” 。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角在下图中标记为 “Finish” 。
问总共有多少条不同的路径
递归
递归的含义就是处理方法不变但是问题的规模减少。
public int uniquePaths(int m, int n)
{//如果只剩一行或者一列那只有一个方向一条路径了if (m 1 || n 1)return 1;//往右走一步问题规模缩小成 m * (n-1) 的网格//往下走一步问题规模缩小成 (m-1) * n 的网格return uniquePaths(m, n - 1) uniquePaths(m - 1, n);
}但在此题中普通的递归解法超时原因是存在大量重复计算。 例如不管是从(0,1)还是(1,0)从来到1,1接下来从1,1到终点都会有2种走法不必每次都重新计算。而普通的递归只能一遍又一遍地计算从1,1到终点有多少种走法。
利用二维数组进行记忆化搜索 每个格子的数字表示从起点开始到达当前位置的路径数计算总路径时可以先查一下记录如果有记录就直接读没有再计算这样就可以避免大量重复计算这就是记忆化搜索。
第一行和第一列都是1。其他格子的值 左侧格子的值 上方格子格子的值。
如图中的4由上面的1和左侧的3计算而来15由上侧的5和左侧的10计算而来。
public int uniquePaths_2(int m, int n)
{int[][] record new int[m][n];record[0][0] 1;for (int row 0; row m; row)for (int col 0; col n; col){if (row 0 col 0)record[row][col] record[row - 1][col] record[row][col - 1];else if (col 0) //第一行格子record[row][col] record[row][col - 1];else if(row 0) //第一列格子record[row][col] record[row - 1][col];}return record[m - 1][n - 1];
}将二维数组优化为一维数组
第一步用1填充一维数组。 第二步从头遍历数组除了第一个位置位置的新值 前一个位置的值 位置的原始值 。其实在二维数组中位置的原始值就在位置新值的上方。 重复第二步 把三个一维数组拼接起来发现恰好跟上面的二维数组一致 所以路径总数就是一维数组最后一个元素的值。
这种反复更新的一维数组就是滚动数组。
public int uniquePaths_3(int m, int n)
{int[] dp new int[n];Arrays.fill(dp,1);for (int row 1; row m; row)for (int col 1; col n; col)dp[col] dp[col - 1] dp[col];return dp[n - 1];
}总结
这个题目涵盖了dp的多个方面比如重复子问题递归、记忆化搜索将已经计算好的结果存入数组后面用到就直接读取、滚动数组二维数组优化为一维数组。
最小路径和
64. 最小路径和 - 力扣LeetCode
给定一个包含非负整数的 *m* x *n* 网格 grid 请找出一条从左上角到右下角的路径使得路径上的数字总和为最小。
**说明**每次只能向下或者向右移动一步
解
public int minPathSum(int[][] grid)
{//逐行遍历更新 grid 的格值作为[在方向约束下从起点到当前格的最小路经和]for (int row 0; row grid.length; row)for (int col 0; col grid[row].length; col){if (row 0 col 0)continue;else if (row 0) //只能往右走grid[row][col] grid[row][col - 1] grid[row][col];else if (col 0) //只能往下走grid[row][col] grid[row - 1][col] grid[row][col];else //从[往右、往下]两个方向挑路径和最小的走grid[row][col] Math.min(grid[row][col - 1], grid[row - 1][col]) grid[row][col];}return grid[grid.length - 1][grid[0].length - 1];
}我们完全不需要建立 dp 矩阵浪费额外空间直接遍历 grid 并修改其值即可。因为原 grid 矩阵元素中被覆盖为 dp 元素后都处于当前遍历点的左上方不会再被使用到。
三角形最小路径和
120. 三角形最小路径和 - 力扣LeetCode
给定一个三角形 triangle 找出自顶向下的最小路径和。
每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 1 的两个结点。也就是说如果正位于当前行的下标 i 那么下一步可以移动到下一行的下标 i 或 i 1 。
示例 1
输入triangle [[2],[3,4],[6,5,7],[4,1,8,3]]
输出11
解释如下面简图所示23 46 5 7
4 1 8 3
自顶向下的最小路径和为 11即 2 3 5 1 11。自底向上 dp 空间优化
public int minimumTotal(ListListInteger triangle)
{int[] dp new int[triangle.size() 1]; //多出一格是为了dp数组能够获取triangle最底层的值// 从最底层开始 dpfor (int row triangle.size() - 1; row 0; row--)for (int col 0; col row 1; col) //第 row 行有 row 1个数dp[col] Math.min(dp[col], dp[col 1]) triangle.get(row).get(col);//顶点储存着从最底层到顶点的最小路径和return dp[0];
}理论上可以直接修改triangle的值而不用额外申请空间但由于triangle的类型是ListListInteger修改起来很繁琐故还是选择申请这O(n)的dp空间
区分动态规划和回溯
动态规划只关心当前结果是什么而不记录结果怎么来的无法获得完整的路径回溯能够获得一条乃至所有满足要求的完整路径。
动态规划题目的三种基本的类型
计数相关。例如求有多少种方式走到右下角有多少种方式选出K个数使得…等等。求最大最小值最多最少。例如最大数字和、最长上升子序列长度、最长公共子序列、最长回文序列等等。求存在性。例如取石子游戏先手是否必胜能不能选出K个数使得…等等。
解决问题的模板
确定状态和子问题。一些题目用逆向思维分析会更容易。确定状态转移方程也就是确定 dp 数组要如何更新状态或者直接在原数组上改动。确定初始条件和边界情况。按照顺序计算。