代码随想录算法训练营第三十二天 | 122. 买卖股票的最佳时机 II、55. 跳跃游戏、45. 跳跃游戏 II
122. 买卖股票的最佳时机 II
题目
解法
- 贪心:局部最优:收集每天的正利润,全局最优:求得最大利润。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int result = 0;
for (int i = 1; i < prices.size(); i++) {
result += max(prices[i]-prices[i-1], 0);
}
return result;
}
};
55. 跳跃游戏
题目
解法
- 转变思维:不用拘泥于每次究竟跳几步,而是看覆盖范围,覆盖范围内一定是可以跳过来的,不用管是怎么跳的。
class Solution {
public:
bool canJump(vector<int>& nums) {
int cover = 0;
if (nums.size() == 1) return true;
for (int i = 0; i <= cover; i++) {
cover = max(i + nums[i], cover );
if (cover >= nums.size() - 1) return true;
}
return false;
}
};
45. 跳跃游戏 II
题目
解法
- 错误:忽略了一次可跳跃范围内可能错过最大的值
class Solution {
public:
int jump(vector<int>& nums) {
// 忽略了一次可跳跃范围内可能错在最大的值
int cover = 0;
if (nums.size() == 1) return 0;
int result = 0;
for (int i = 0; i < nums.size(); i++) {
if(i + nums[i] > cover) { // 范围更新一次就加一
cover = i + nums[i];
result++;
};
if (cover >= nums.size() - 1) return result;
}
return result;
}
};
2.探索可以跳跃的最远距离
class Solution {
public:
int jump(vector<int>& nums) {
// 忽略了一次可跳跃范围内可能错在最大的值
if (nums.size() == 1) return 0;
int curDistance = 0;
int nextDistance = 0;
int result = 0;
for (int i = 0; i < nums.size(); i++) {
nextDistance = max(i + nums[i], nextDistance); //下次可以跳跃的最远距离
if (i == curDistance) { // 达到目前可跳跃的最远距离
result++; //目前可跳跃的最远距离达不到终点, 需要下一次跳跃
curDistance = nextDistance; // 更新目前可跳跃的最远距离
if (nextDistance >= nums.size() - 1) break;
}
}
return result;
}
};
3.特殊处理:针对题中生成的测试用例可以到达 nums[n - 1]。只要能达到倒数第二个,直接加一
class Solution {
public:
int jump(vector<int>& nums) {
int curDistance = 0; // 当前覆盖的最远距离下标
int ans = 0; // 记录走的最大步数
int nextDistance = 0; // 下一步覆盖的最远距离下标
for (int i = 0; i < nums.size() - 1; i++) { // 注意这里是小于nums.size() - 1,这是关键所在
nextDistance = max(nums[i] + i, nextDistance); // 更新下一步覆盖的最远距离下标
if (i == curDistance) { // 遇到当前覆盖的最远距离下标
curDistance = nextDistance; // 更新当前覆盖的最远距离下标
ans++;
}
}
return ans;
}
};
感悟
局部最优可以推出全局最优,找不出反例,试一试贪心!
转变思维好难!