题目链接
代码随想录文章讲解链接
用时:22m45s
dp数组:dp[i][0]表示第i天没有买入过股票,dp[i][2j+1]表示第i天第j+1次持有股票,dp[i][2j]表示第i天第j+1次不持有股票
状态转移:状态转移跟123m题一样
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
if (prices.size() == 0) return 0;
vector<int> dp(2 * k + 1, 0);
for (int j = 1; j < dp.size(); j += 2) dp[j] = -prices[0];
for (int i = 1; i < prices.size(); ++i) {
for (int j = dp.size() - 1; j >= 2; j -= 2) {
dp[j] = max(dp[j], dp[j - 1] + prices[i]); // 第i次不持有
dp[j - 1] = max(dp[j - 1], dp[j - 2] - prices[i]); // 第i次持有
}
}
return dp[2 * k];
}
};
无。
无。
题目链接
代码随想录文章讲解链接
用时:25m59s
dp数组:dp[i][0]表示第i天持有股票的收支,dp[i][1]表示第i天不持有股票且第i-1天也不持有股票的收支,dp[i][2]表示第i天不持有股票且第i-1持有股票的收支。
状态转移:
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i])
dp[i][1] = max(dp[i - 1][1], dp[i - 1][2])
dp[i][2] = dp[i - 1][0] + prices[i]
class Solution {
public:
int maxProfit(vector<int>& prices) {
int size = prices.size();
vector<vector<int>> dp(size, vector<int>(3, 0)); // dp数组
dp[0][0] = -prices[0]; // dp数组初始化
for (int i = 1; i < size; ++i) { // 状态转移
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][2]);
dp[i][2] = dp[i - 1][0] + prices[i];
}
return max(dp[size - 1][1], dp[size - 1][2]);
}
};
用时:2m54s
在方法一的基础上,dp数组使用一维数组。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int size = prices.size();
vector<int> dp(3, 0); // dp数组
dp[0] = -prices[0]; // dp数组初始化
for (int i = 1; i < size; ++i) { // 状态转移
int tmp = dp[0] + prices[i];
dp[0] = max(dp[0], dp[1] - prices[i]);
dp[1] = max(dp[1], dp[2]);
dp[2] = tmp;
}
return max(dp[1], dp[2]);
}
};
无。
无。
题目链接
代码随想录文章讲解链接
用时:4m11s
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int dp0 = -prices[0] - fee, dp1 = 0;
for (int i = 1; i < prices.size(); ++i) {
int tmp = max(dp0, dp1 - prices[i] - fee);
dp1 = max(dp1, dp0 + prices[i]);
dp0 = tmp;
}
return dp1;
}
};
无。
无。
题目链接
代码随想录文章讲解链接
用时:16m37s
对于第i个元素nums[i],以nums[i]开头的最长严格递增子序列(LIS)的长度,等于1加上以nums[i]之后的大于nums[i]的元素为开头的LIS的最大长度,用一个数组记录以每个元素为开头的LIS的最大长度,由后往前遍历,因为前面的LIS长度依赖于后面的值。
得到全部LIS长度后,最大值即为答案。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> vec(nums.size(), 1);
int res = 1;
for (int i = nums.size() - 1; i >= 0; --i) {
for (int j = i + 1; j < nums.size(); ++j) {
if (nums[j] > nums[i]) vec[i] = max(vec[i], 1 + vec[j]);
}
}
for (int& n : vec) {
if (n > res) res = n;
}
return res;
}
};
用时:15m31s
数组last:last[i]表示长度为i的子序列的最小末尾元素。
贪心思想:为了让子序列尽可能的长,所以子序列的末尾元素要尽可能的小
遍历数组,若当前元素n大于last数组最后一个元素,则递增子序列可以增长,并且n是作为末尾元素,所以将n添加到last数组末尾。若n小于last数组最后一个元素,则递增子序列无法增长,但是可以按照贪心思想更新last数组:找到大于n的第一个数,将其替换成n,由于last是递增数组,所以可以用二分查找。
最后的答案就是last数组的长度。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> last;
last.push_back(nums[0]);
for (int i = 1; i < nums.size(); ++i) {
int target = nums[i];
if (target > last.back()) last.push_back(target);
else if (target < last.back()) {
// 二分查找
int left = 0, right = last.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (last[mid] < target) left = mid + 1;
else right = mid - 1;
}
last[left] = target;
}
}
return last.size();
}
};
无。
无。
题目链接
代码随想录文章讲解链接
用时:7m26s
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
int left = 0, right = 0;
int res = 1;
while (++right < nums.size()) {
if (nums[right] <= nums[right - 1]) {
res = max(res, right - left);
left = right;
}
}
return max(res, right - left);
}
};
用时:5m7s
dp数组:dp[i]表示以nums[i]为结尾的连续递增子序列的最大长度。
状态转移:如果nums[i]大于nums[i-1],则dp[i] = dp[i-1] + 1
;否则dp[i] = 1
。
最后答案是dp数组中的最大值。由于状态转移只与前一个状态有关,所以可以用一个变量记录前一个状态即可。
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
int dp = 1;
int res = 1;
for (int i = 1; i < nums.size(); ++i) {
if (nums[i] > nums[i - 1]) ++dp;
else dp = 1;
if (dp > res) res = dp;
}
return res;
}
};
无。
无。
题目链接
代码随想录文章讲解链接
用时:21m15s
逐个子数组遍历,逐个匹配。
class Solution {
public:
int findLength(vector<int>& nums1, vector<int>& nums2) {
int idx1 = 0;
int size1 = nums1.size(), size2 = nums2.size();
int res = 0;
while (idx1 < size1) {
for (int i = 0; i < size2 - res; ++i) {
if (nums2[i] == nums1[idx1]) {
int offset = 1;
if (res == 0) res = 1;
while (idx1 + offset < size1 && i + offset < size2 && nums1[idx1 + offset] == nums2[i + offset]) {
++offset;
res = max(res, offset);
}
}
}
++idx1;
}
return res;
}
};
用时:5m52s
dp数组:二维dp数组,dp[i][j]
表示nums1
中以nums1[i - 1]
为结尾的子数组和nums2
中以nums2[j - 1]
为结尾的子数组的最长公共子数组的长度。
状态转移:若nums1[i - 1] == nums2[j - 1]
,则dp[i][j] = dp[i - 1][j - 1] + 1
。
class Solution {
public:
int findLength(vector<int>& nums1, vector<int>& nums2) {
int size1 = nums1.size(), size2 = nums2.size();
int res = 0;
vector<vector<int>> dp(size1 + 1, vector<int>(size2 + 1, 0));
for (int i = 1; i <= size1; ++i) {
for (int j = 1; j <= size2; ++j) {
if (nums1[i - 1] == nums2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
res = max(res, dp[i][j]);
}
}
return res;
}
};
用时:5m3s
方法二空间可以用滚动数组优化。
class Solution {
public:
int findLength(vector<int>& nums1, vector<int>& nums2) {
int size1 = nums1.size(), size2 = nums2.size();
int res = 0;
vector<int> dp(size2 + 1, 0);
for (int i = 1; i <= size1; ++i) {
for (int j = size2; j >= 1; --j) {
if (nums1[i - 1] == nums2[j - 1]) dp[j] = dp[j - 1] + 1;
else dp[j] = 0;
res = max(res, dp[j]);
}
}
return res;
}
};
无。
无。
题目链接
代码随想录文章讲解链接
用时:11m12s
dp数组:二维dp数组,dp[i][j]表示text1[:i]和text2[:j]的最长公共子序列的长度。
状态转移:见代码。
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int len1 = text1.length(), len2 = text2.length();
vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1, 0));
for (int i = 1; i <= len1; ++i) {
for (int j = 1; j <= len2; ++j) {
if (text1[i - 1] == text2[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[len1][len2];
}
};
无。
无。
好多天没刷题了,中秋国庆假疯狂摆烂,然后最近又在忙比赛的事儿。
今天暴刷7题,找找手感,还好生疏太多。