LeetCode 55:
题目

分析
推荐用贪心,思路就是不断去更新能够跳到的最大值,如果大于等于n-1,那么就能跳到最后,反之不能。
但是我自己写的时候,是用的递归,就是倒着算回去,这在这道题中不是最优解,但如果nums数组含义变了,变成nums[i]表示"只能从第i格跳nums[i]步",那就只能用这个更好
代码
贪心:
cpp
class Solution {
public:
bool canJump(vector<int>& nums) {
int farthest = 0;
for (int i = 0; i < nums.size(); i++) {
if (i > farthest) return false;//采用最长的组合都跳不到第i格
farthest = max(farthest, i + nums[i]);//更新最长的组合
}
return true;
}
};
递归:
cpp
class Solution {
private:
bool recursion(vector<int> & array,int pos){
if(pos == 0) return 1;
for(int i = 0;i<pos;i++){
if(array[i] >= pos - i)
return recursion(array,i);
}
return 0;
}
public:
bool canJump(vector<int>& nums) {
return recursion(nums,nums.size()-1);
}
};
结果
贪心:

递归:

LeetCode 213:
题目

分析
和I区别不大,但是多了一个首尾相连,这导致两端不能同时被抢,在写完主体后,在这里被卡住了,看了题解是要么抢第一家(也就是考虑0-n-2)、要么抢最后一家(也就是考虑1-n-1),然后两个来取最大值。(此时两个都不抢已经被隐式包含了)
代码
cpp
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
if (n == 1) return nums[0];
if (n == 2) return max(nums[0], nums[1]);
// 情况1:不抢第一家 → [1, n-1]
vector<int> nums1(nums.begin() + 1, nums.end());
// 情况2:不抢最后一家 → [0, n-2]
vector<int> nums2(nums.begin(), nums.end() - 1);
return max(robLinear(nums1), robLinear(nums2));
}
private:
int robLinear(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> dp(n, vector<int>(2, 0));
dp[0][1] = nums[0];
for (int i = 1; i < n; ++i) {
dp[i][0] = max(dp[i-1][0], dp[i-1][1]);
dp[i][1] = dp[i-1][0] + nums[i];
}
return max(dp[n-1][0], dp[n-1][1]); // 更简洁,不用排序
}
};
结果

LeetCode 123:
题目

分析
感觉这些依靠前一天或者前面的状态的dp问题都是一个套路,重点是规划好合适dp数组对应的状态,这里的dp数组就是0-4分别对应:无操作、第一次买、第一次卖、第二次买、第二次卖。
注意这里是指包括第i天在内,这之前都是这种状态,比如dp[i][1]就是在第i天以及之前就已经买入了或者第i天才买入,诸如此类。
代码
cpp
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n<=1)return 0;
vector<vector<int>>dp(n,vector<int>(5,0));//0-在此之前一直(包括现在)一直都没有操作
//1-在此之前一直(包括现在)第一次买入
//2-在此之前一直(包括现在)第一次卖出
//3-在此之前一直(包括现在)第二次买入
//4-在此之前一直(包括现在)第二次卖出
dp[0][1] = -prices[0];
dp[0][3] = -prices[0];
for(int i = 1;i < n;i++){
dp[i][0] = dp[i-1][0];
dp[i][1] = max(dp[i-1][1],dp[i-1][0]-prices[i]);//这一天第一次买入或者保持
dp[i][2] = max(dp[i-1][2],dp[i-1][1]+prices[i]);//这一天第一次卖出或者保持
dp[i][3] = max(dp[i-1][3],dp[i-1][2]-prices[i]);//这一天第二次买入或者保持
dp[i][4] = max(dp[i-1][4],dp[i-1][3]+prices[i]);//这一天第二次卖出或者保持
}
return dp[n-1][4];
}
};
结果

还有一种是用滚动变量来做,代码:

这个在复杂度上肯定要好得多,不过我的代码是比较"泛用"吧(或许这个也挺泛用,但我不熟悉,嘻嘻)