【前言】OJ:AcWing + LeetCode 。活动:b站 大雪菜 。
动态规划02
1 最长上升子序列
题目描述
给定一个无序的整数数组,找到其中最长上升子序列的长度。
说明:
可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
样例
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
笔记
代码
/*
法一:DP
法二:贪心
*/
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
vector<int> f(n); //以i为下标时,最长子序列长度
for(int i=0;i<n;i++){
f[i]=1; //只有 i 自己时
for(int j=0;j<i;j++){
if(nums[j]<nums[i]) f[i]=max(f[i],f[j]+1);
}
}
int res=0;
for(int i=0;i<n;i++)
res= res>f[i]?res:f[i];
return res;
}
};
2 编辑距离
题目描述
给定两个单词 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’)
笔记
代码
class Solution {
public:
int minDistance(string word1, string word2) {
int n=word1.size(),m=word2.size();
vector<vector<int>> f(n+1,vector<int>(m+1));
for(int i=0;i<=n;i++) f[i][0]=i;
for(int i=0;i<=m;i++) f[0][i]=i;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
f[i][j]=min(f[i-1][j],f[i][j-1])+1;
f[i][j]=min(f[i][j],f[i-1][j-1]+(word1[i-1]!=word2[j-1]));
}
}
return f[n][m];
}
};
3 零钱兑换 II
题目描述
给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。
注意:
你可以假设:
0 <= amount (总金额) <= 5000
1 <= coin (硬币面额) <= 5000
硬币种类不超过 500 种
结果符合 32 位符号整数
样例
示例 1:
输入: amount = 5, coins = [1, 2, 5]
输出: 4
解释: 有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
示例 2:
输入: amount = 3, coins = [2]
输出: 0
解释: 只用面额2的硬币不能凑成总金额3。
示例 3:
输入: amount = 10, coins = [10]
输出: 1
笔记
化简:
代码
/*
完全背包问题 f[j] 当总金额为j时,硬币组合方式
*/class Solution {
public:
int change(int m, vector<int>& coins) {
int n=coins.size();
vector<int> f(m+1);
f[0]=1;
for(auto c:coins){
for(int j=c;j<=m;j++){
f[j]=f[j]+f[j-c];
}
}
return f[m];
}
};
4 奇怪的打印机
题目描述
样例
笔记
- 由数据范围反推算法复杂度以及算法内容:https://www.acwing.com/blog/content/32/
代码
/*
DP 要保证算每个状态时,所需条件都已经有值,所以从小到大遍历
*/
class Solution {
public:
int strangePrinter(string s) {
if(s.empty()) return 0;
int n=s.size();
vector<vector<int>> f(n+1,vector<int>(n+1));
for(int len=1;len<=n;len++){
for(int l=0;l+len-1<n;l++){
int r=l+len-1;
f[l][r]=f[l+1][r]+1;
for(int k=l+1;k<=r;k++){
if(s[k]==s[l])
f[l][r]=min(f[l][r],f[l][k-1]+f[k+1][r]);
}
}
}
return f[0][n-1];
}
};