hot100-一刷-16多维动态规划(共5道题)
62. 不同路径
题目描述
代码实现
分析:
代码:
class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
//dp[i][j] = dp[i-1][j] + dp[i][j-1];
for (int i = 0; i<m; i++) dp[i][0] = 1;
for (int j = 0; j<n; j++) dp[0][j] = 1;
for(int i = 1; i < m; i++){
for(int j = 1; j < n; j++){
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
}
}
64. 最小路径和
题目描述
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 200
0 <= grid[i][j] <= 200
代码实现
分析:
代码:
class Solution {
public int minPathSum(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
// dp[i][j] 表示 从[0][0]到[i][j]路径上最小的数字和。
int[][] dp = new int[m][n];
dp[0][0] = grid[0][0];
for(int i = 1; i < m; i++) dp[i][0] = dp[i-1][0] + grid[i][0];
for(int j = 1; j < n; j++) dp[0][j] = dp[0][j-1] + grid[0][j];
for(int i = 1; i < m; i++){
for(int j = 1; j < n; j++){
dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1]) + grid[i][j];
}
}
return dp[m-1][n-1];
}
}
5. 最长回文子串
题目描述
给你一个字符串 s,找到 s 中最长的 回文 子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
代码实现
分析:
代码:
class Solution {
public String longestPalindrome(String s) {
char[] chars = s.toCharArray();
int n = s.length();
// [i,j]是回文依赖于 [i+1, j-1]是回文 且 s[i] = s[j]
// 初始默认都没匹配上
boolean[][] dp = new boolean[n][n];
int res = 0;
String ans = "";
// 从下到上,
for(int i = n-1; i >=0; i--){
// 从左到右
for(int j = i; j < n; j++){
if(chars[i] == chars[j]){
// i和j相等, 或者,i比j小1, 分别是 ‘a’ ‘aa’这两种情况
if(j - i <= 1){
dp[i][j] = true;
res = Math.max(j-i, res);
if(j - i >= res){
ans = s.substring(i, j+1);
}
}else { // 'cabac'这种情况,继续判断[i+1, j-1]的情况
if(dp[i+1][j-1]){ //从下到上,从左到右的遍历顺序,此时用到的是已经更新过的dp[i+1][j-1]
dp[i][j] = true;
res = Math.max(j-i, res);
if(j - i >= res){
ans = s.substring(i, j+1);
}
}
}
}
}
}
return ans;
}
}
// 简洁版
class Solution {
public String longestPalindrome(String s) {
char[] chars = s.toCharArray();
int n = s.length();
// [i,j]是回文依赖于 [i+1, j-1]是回文 且 s[i] = s[j]
// 初始默认都没匹配上
boolean[][] dp = new boolean[n][n];
int res = 0;
String ans = "";
// 从下到上,
for(int i = n-1; i >=0; i--){
// 从左到右
for(int j = i; j < n; j++){
if(chars[i] == chars[j] && (j-i <=1 || dp[i+1][j-1])){
// i和j相等, 或者,i比j小1, 分别是 ‘a’ ‘aa’这两种情况
// 'cabac'这种情况,继续判断[i+1, j-1]的情况 //从下到上,从左到右的遍历顺序,此时用到的是已经更新过的dp[i+1][j-1]
dp[i][j] = true;
res = Math.max(j-i, res);
if(j - i >= res){
ans = s.substring(i, j+1);
}
}
}
}
return ans;
}
}
1143. 最长公共子序列
题目描述
给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。
示例 1:
输入:text1 = "abcde", text2 = "ace"
输出:3
解释:最长公共子序列是 "ace" ,它的长度为 3 。
示例 2:
输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc" ,它的长度为 3 。
示例 3:
输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0 。
提示:
1 <= text1.length, text2.length <= 1000
text1 和 text2 仅由小写英文字符组成。
代码实现
分析:
代码:
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length();
int n = text2.length();
// dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]
int[][] dp = new int[m+1][n+1];
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
if(text1.charAt(i-1) == text2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = Math.max(dp[i][j-1], dp[i-1][j]);
}
}
}
// [0, m-1]的text1 和 [0,n-1] 的text2 的最长公共子序列长度
return dp[m][n];
}
}
72. 编辑距离
题目描述
给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符
示例 1:
输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
示例 2:
输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')
提示:
0 <= word1.length, word2.length <= 500
word1 和 word2 由小写英文字母组成
代码实现
分析:
代码:
class Solution {
public int minDistance(String word1, String word2) {
int len1 = word1.length();
int len2 = word2.length();
// dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]
int[][] dp = new int [len1+1][len2+1];
for (int i = 1; i <=len1; i++) dp[i][0] = i; // word2为空,word1有几个单词,word1就删除几个单词
for (int j = 1; j <= len2; j++) dp[0][j] = j;// word1为空,word2有几个单词, word1就增加几个单词
for(int i = 1; i <= len1; i++){
for(int j = 1; j <= len2; j++){
if(word1.charAt(i-1) == word2.charAt(j-1)){
// 无操作
dp[i][j] = dp[i-1][j-1];
}else{
// [[插入(word1插入一个和word2一样的单词,相当于word2删除那个单词), 删除], 替换]
dp[i][j] = Math.min(Math.min(dp[i][j-1],dp[i-1][j]), dp[i-1][j-1]) + 1;
}
}
}
return dp[len1][len2];
}
}
本文来自博客园,作者:chendsome,转载请注明原文链接:https://www.cnblogs.com/chendsome/p/18644642