算法學習笔记
动态规划
最长递增子序列问题(Longest Increasing Subsequence)
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,
[3,6,2,7]
是数组[0,3,1,6,2,2,7]
的子序列。
这是我写的代码(有点差劲的代码
class Solution {
public:
vector<int> dp;
int tryThrough(vector<int>& nums) {
int res = 0x80000000;
for (int i = 0; i < nums.size(); i++) {
if(dp[i] > res){
res = dp[i];
}
}
return res;
}
int lengthOfLIS(vector<int>& nums) {
dp.push_back(1);
for (int i = 1; i < nums.size(); i++) {
dp.push_back(1);
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j] && dp[j] >= dp[i])
dp[i] = dp[j] + 1;
}
}
for (auto& tmp : dp) {
std::cout << tmp << ' ';
}
return tryThrough(nums);
}
};
写的过程中出现了一下几个问题
- tryThrough 函数中把 dp[i] 写成 nums[i],遗忘了需要遍历的是子序列的长度
- lengthOfLIS 中一开始习惯性的认为需要前两个元素 dp[0] 和 dp[1],而且想当然的认为 dp[1] 等一 1,实际上我一边认为 dp[0] 应该是某种虚的最长子序列,另一边我认为 dp[i] 表示长度 i+1 的以 nums[i] 结尾的最长子序列。
- 在处理
dp[j] >= dp[i]
时,写成了dp[j] > dp[i]
,想当然的认为大于才能递增,实际上可能存在相等的情况,这里正确的逻辑应该是max(dp[i],dp[j]+1)
再来看一下优秀代码,leetcode 官网的优雅代码
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = (int)nums.size();
if (n == 0) {
return 0;
}
vector<int> dp(n, 0);
for (int i = 0; i < n; ++i) {
dp[i] = 1;
for (int j = 0; j < i; ++j) {
if (nums[j] < nums[i]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
return *max_element(dp.begin(), dp.end());
}
};
最长公共子序列(Longest Common Subsequence)
𝑆1 = ACCGGTCGAGTGCGCGGAAGCCGGCCGAA
𝑆2 = GTCGTTCGGAATGCCGTTGCTCTGTAAA
𝐿𝐶𝑆 = GTCGTCGGAAGCCGGCCGAA
未完待续
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 R0gerThat!
评论