题目链接
代码随想录文章讲解链接
用时:15m11s
dp数组:二维dp,dp[i][j]表示nums1[:i]和nums2[:j]的最大连线数。
状态转移:当nums1[i]==nums2[j]时,让这两个数连线一定是当前最优的情况,所以连线数就等于dp[i - 1][j - 1] + 1;当不相等时,连线数就等于去掉nums1[i]或者nums2[j]的连线数中的最大值。
class Solution {
public:
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
vector<vector<int>> dp(nums1.size() + 1, vector<int>(nums2.size() + 1, 0));
for (int i = 1; i <= nums1.size(); ++i) {
for (int j = 1; j <= nums2.size(); ++j) {
if (nums1[i - 1] == nums2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[nums1.size()][nums2.size()];
}
};
用时:18m
方法一可以用滚动数组优化空间,但是由于数组更新的时候会覆盖原来dp[i-1][j-1]的值,所以需要中间变量临时存储方法一中的dp[i-1][j-1]的值,由于当前dp[i][j]的值对于下一个位置也是所需要的值,在更新当前dp[i][j]的值时也需要先存储,所以就需要两个临时变量。
更新dp[i][j]的值时,首先用tmp2记录当前dp值,然后更新当前dp值,注意,如果是相等的情况,需要用到tmp1更新,更新后,由于要移动到下一个位置,将tmp2赋值给tmp1。
注意内层循环结束后,tmp1要移到开头。
class Solution {
public:
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
vector<int> dp(nums2.size() + 1, 0);
int tmp1 = 0, tmp2 = 0;
for (int i = 1; i <= nums1.size(); ++i) {
tmp1 = dp[0]; // 注意!
for (int j = 1; j <= nums2.size(); ++j) {
tmp2 = dp[j];
if (nums1[i - 1] == nums2[j - 1]) dp[j] = tmp1 + 1;
else dp[j] = max(dp[j - 1], dp[j]);
tmp1 = tmp2;
}
}
return dp[nums2.size()];
}
};
无。
本题滚动数组优化空间有点绕,一开始还以为只用一个临时变量,想了半天才发现得用两个变量,然后一开始还没讲tmp1移至开头。
题目链接
代码随想录文章讲解链接
用时:13m38s
dp数组:dp[i]表示以nums[i]为结尾的连续子数组的最大和。
状态转移:对于nums[i],有两种情况,一是nums[i]连接上nums[i-1]的子数组,二是nums[i]重新开头作为子数组,最大和为两者的最大值。
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int dp = 0, res = INT_MIN;
for (int& n : nums) {
dp = max(dp + n, n);
if (dp > res) res = dp;
}
return res;
}
};
无。
无。
题目链接
代码随想录文章讲解链接
class Solution {
public:
bool isSubsequence(string s, string t) {
int idx1 = 0, idx2 = 0;
while (idx1 < s.length() && idx2 < t.length()) {
if (s[idx1] == t[idx2++]) ++idx1;
}
return idx1 == s.length();
}
};
无。
无。
题目链接
代码随想录文章讲解链接
用时:
用时:
题目链接
代码随想录文章讲解链接
用时:12m58s
dp数组:二维dp数组,dp[i][j]表示s[:i]的子序列中出现s[:j]的个数。
状态转移:
class Solution {
public:
int numDistinct(string s, string t) {
vector<vector<unsigned int>> dp(s.length() + 1, vector<unsigned int>(t.length() + 1, 0));
for (int i = 0; i <= s.length(); ++i) {
dp[i][0] = 1;
for (int j = 1; j <= i && j <= t.length(); ++j) {
if (s[i - 1] == t[j - 1]) dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
else dp[i][j] = dp[i - 1][j];
}
}
return int(dp[s.length()][t.length()] % (1000000000 + 7));
}
};
用时:8m28s
方法一的空间优化版本。
class Solution {
public:
int numDistinct(string s, string t) {
vector<unsigned int> dp(t.length() + 1, 0);
dp[0] = 1;
for (int i = 1; i <= s.length(); ++i) {
for (int j = min(i, int(t.length())); j > 0; --j) {
if (s[i - 1] == t[j - 1]) dp[j] += dp[j - 1];
}
}
return int(dp[t.length()] % (1000000000 + 7));
}
};
无。
无。
二维dp刷出手感了,dp数组的含义基本都差不多,关键点还是在于状态转移。