
动态规划
圆滚滚的柴柴
这个作者很懒,什么都没留下…
展开
-
牛客 剑指offer:最小编辑代价
题目:最小编辑代价思路:动态规划。leetcode类似的题目,三个操作的代价都是1,把问题抽象为三种情况:对a删除、对b删除、替换;而这道题三种操作的代价不同,而且只能对一个字符串修改,所以把问题抽象成:对a删除、对a插入、替换。转移方程如下:如果s1[i] == s2[j],则 dp[i][j] = dp[i - 1][j - 1]。即,如果当前字符相等,那么此时不需要额外操作;如果s1[i] != s2[j],则 dp[i][j] = Math.min(Math.min(dp[i][j - 1原创 2021-04-09 11:00:54 · 132 阅读 · 0 评论 -
leetcode Java:72. 编辑距离
题目:72. 编辑距离思路:动态规划。一共三种操作:插入、删除、替换。一对字符串a和b:对a插入相等于对b删除;对a删除相当于对b插入;对a替换相当于对b替换。所以,转移方程:如果s1[i] == s2[j],则 dp[i][j] = dp[i - 1][j - 1]。即,如果当前字符相等,那么此时不需要额外操作;如果s1[i] != s2[j],则 dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j -原创 2021-04-08 16:26:56 · 113 阅读 · 0 评论 -
牛客 剑指offer:最长公共子序列
题目:最长公共子序列思路:动态规划。dp[i][j]表示s1以i结尾,s2以j结尾的公共子序列长度,递推公式:如果str1[i] == str2[j],则 dp[i][j] = dp[i - 1][j - 1] + 1如果str1[i] != str2[j],则 dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])有了这个dp数组,我们反推公共序列。从dp数组的右下角开始:如果两个字符相等,加入结果,然后下一步位置是左上角;如果两个字符不相等,那原创 2021-04-01 11:33:59 · 249 阅读 · 0 评论 -
牛客 剑指offer:最长公共子串
题目:最长公共子串思路:动态规划dp[i][j]表示str1以i结尾,str2以j结尾的最长公共子串的个数,递推公式:如果str1[i] == str2[j],则 dp[i][j] = dp[i - 1][j - 1] + 1如果str1[i] != str2[j],则 dp[i][j] = 0有了这个dp数组,如何得到具体子串呢?我们在更新dp数组时,维护一个最大长度和最大子串的最终位置,每得到一个更长的子串,就更新最大长度和此时的位置,最后,用结尾的位置减去长度就可以得到子串的起始位置。原创 2021-03-30 17:27:42 · 162 阅读 · 0 评论 -
leetcode Java:64. 最小路径和
题目:64. 最小路径和思路:动态规划。仍然与上一题类似,某个位置的路径和只依赖上方和左方,取二者较小的一个,加上当前位置的值即为该位置的最小路径和。代码:class Solution { public int minPathSum(int[][] grid) { int m = grid.length; int n = grid[0].length; int[] dp = new int[n + 1]; Arrays.fill原创 2021-03-29 17:59:04 · 91 阅读 · 1 评论 -
leetcode Java:63. 不同路径 II
题目:63. 不同路径 II思路:动态规划。在上一题的基础上,加一条判断,如果有障碍,dp置为0即可。代码:class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0].length; int[] dp = new int[n]; d原创 2021-03-29 17:14:18 · 88 阅读 · 0 评论 -
leetcode Java:62. 不同路径
题目:62. 不同路径思路:动态规划。很显然,二维数组的转移方程:dp[i][j] = dp[i-1][j] + dp[i][j-1]优化:当前位置的路径数,指取决于数组中它的上方和左方,因此,一个n维数组即可满足需求。转移方程:dp[j] = dp[j] + dp[j - 1]方程右侧:dp[j]是上一行的值,即上方;dp[j - 1]是本行已经更新的值,即左方。代码:class Solution { public int uniquePaths(int m, int n) {原创 2021-03-29 16:43:04 · 114 阅读 · 0 评论 -
牛客 剑指offer:不相邻最大子序列和
题目:不相邻最大子序列和思路:动态规划。dp[i]为数组中以下标i结尾的最大子序列和,很显然,dp[i]要么是array[i]本身,要么是dp[i - 1],要么是array[i] + dp[i - 2]。所以转移方程:dp[i] = Math.max(Math.max(array[i], dp[i - 1]), dp[i - 2] + array[i])代码:import java.util.*;public class Solution { /** * 代码中的类名、原创 2021-03-23 15:32:13 · 416 阅读 · 0 评论 -
牛客 剑指offer:最长递增子序列
题目:最长递增子序列思路:首先,动态规划可以解决。定义dp[i]为以i结尾的数组的最长递增子序列的长度,对于i之前的位置j,如果数组i处的值大于j,那么dp[i]可以在dp[j]的基础上加1。我们遍历i之前的位置,取最大值。得到dp数组后,其中的最大值就是最长递增子序列的长度,如何得到序列呢?反向遍历dp数组即可。例如:arr:[2, 1, 5, 3, 6, 4, 8, 9, 7]dp:[1, 1, 2, 2, 3, 3, 4, 5, 4]我们倒叙遍历dp,挨个找。找第5个位置:9找第4个原创 2021-03-22 21:08:39 · 280 阅读 · 0 评论 -
leetcode Java:174. 地下城游戏
题目:174. 地下城游戏思路:动态规划。假设有一条路径:-2,-5,10,30,-5。如果正向找初始值,我们需要存两个值,满足需求的起点健康值和达到每个位置时需要的最少健康值:每个位置需要的最少健康值依赖前一个位置;满足需求的起点健康值就是在每个位置需要的最少健康值中取最大的(1也参与比较,因为有可能路径全为正值)。如果反向找:下图从右到左看。我们无需额外计算起点健康值,在起点处的值就是我们想要的答案。所以,我们动态规划是从终点开始搜索。dp[i][j]表示坐标(i,j)到达终点需要的健原创 2021-03-19 14:21:45 · 193 阅读 · 0 评论 -
leetcode Java:53. 最大子序和
题目:53. 最大子序和思路:动态规划。dp[i]表示,数组以索引i结尾的最大字序和,很显然:dp[i] = Math.max(nums[i], nums[i] + dp[i - 1])由于dp[i]只和前一个值dp[i -1]有关,因此可以对空间进行优化。代码:优化class Solution { public int maxSubArray(int[] nums) { int n = nums.length; int dp = nums[0];原创 2021-03-15 16:20:27 · 101 阅读 · 0 评论 -
leetcode Java:152. 乘积最大子数组
题目:152. 乘积最大子数组思路:动态规划。由于数字有正有负,我们记录以每个位置结尾的最大乘积和最小乘积,避免漏掉负负得正的情况。那么,每个位置结尾的最大乘积,由三个值来比较:该位置的值、该位置的值乘上个位置的最大积、该位置的值乘上上个位置的最小积;三者取最大。同理,每个位置结尾的最大乘积也由上述的三个值确定,三者取最小。代码:class Solution { public int maxProduct(int[] nums) { int n = nums.length原创 2021-03-05 17:35:29 · 131 阅读 · 0 评论 -
leetcode Java二刷:44. 通配符匹配
题目:44. 通配符匹配思路:动态规划详细思路见:通配符匹配代码:class Solution { public boolean isMatch(String s, String p) { int sl = s.length(); int pl = p.length(); boolean dp[][] = new boolean[sl + 1][ pl + 1]; dp[0][0] = true; for (in原创 2021-03-02 15:40:10 · 72 阅读 · 0 评论 -
leetcode Java二刷:32. 最长有效括号
题目:32. 最长有效括号思路:动态规划。dp[i]表示以s[i]结尾的最长有效括号的长度 易知:若s[i]是左括号,则必然不是一个有效的括号,此时对应的dp[i]为0。若s[i]为右括号,s[i]对应的dp[i]分如下两种情况:如果s[i-1]=="(",即形如"......()",那么此时配对成功,可以推出: dp[i] = dp[i-2]+2即以s[i-2]结尾的最长有效括号加上新的一对有效括号。如果s[i-1]==")",即形如"......))",那么我们需要检原创 2021-02-19 15:32:46 · 68 阅读 · 0 评论 -
leetcode Java二刷:10. 正则表达式匹配
题目:10. 正则表达式匹配思路:动态规划若s[i] == p[j],或者p[j] == '.',那么s[i]与p[j]匹配,转移方程:dp[i][j] = dp[i - 1][j - 1]若s[i] != p[j],并且p[j] == '*',此时,p往前看一位:s[i] != p[j-1],表示s[i]无法与*前的字母匹配,因此dp[i][j] = dp[i][j - 2]s[i] == p[j-1],此时分3种情况:(1) s[i]与p[j-1]匹配,dp[i][j] = dp[i][原创 2021-01-06 15:08:36 · 96 阅读 · 0 评论 -
leetcode Java二刷:5. 最长回文子串
题目:5. 最长回文子串思路:动态规划数组dp[i][j]表示s[i:j]是否是一个动态数组。我们先枚举子串的长度,再枚举子串的起始位置,填充dp数组。如果子串长度是1,那么它必定是一个回文串;如果子串长度是2,那么只有两个字母相等才是回文串;如果子串长度大于等于3,那么dp[i][j] = dp[i+1][j-1] && s[i]==s[j]。因为若dp[i][j]是回文,则dp[i+1][j-1]也是。代码:class Solution { public St原创 2020-12-25 10:08:19 · 118 阅读 · 0 评论