Day32_贪心算法
6. 买卖股票的最佳时机 II
遇到第二天会涨的股票都买,第二天卖掉。
遇到第二天会跌的股票就不买。
由于连续上升的股票多次买卖与开始买入到上升结束时卖出得到的收益是一样的,所以上面的思路是正确的。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int prices_size = prices.size();
int max_profit = 0;
for (int i = 0; i < prices_size - 1; ++i) {
if (prices[i] < prices[i + 1]) {
max_profit += (prices[i + 1] - prices[i]);
}
}
return max_profit;
}
};
7. 跳跃游戏
55. 跳跃游戏
思路:
每跳一次都更新当前还可以跳跃的步长,如果剩余步长为0,则不允许继续跳跃,如果还没有跳跃到最后,则不能完成跳跃任务。
每跳跃一次,步长 -1 ,更新时,步长更新为当前剩余步长和当前格可以跳的最大长度的最大值。
class Solution {
public:
bool canJump(vector<int>& nums) {
int nums_size = nums.size();
int rest_step = nums[0];
for (int i = 1; i < nums_size; ++i) {
if (!rest_step) return false;
rest_step--;
rest_step = max(rest_step, nums[i]);
}
return true;
}
};
8. 跳跃游戏 II
45. 跳跃游戏 II
思路:
在当前点的可达范围内,选择能让下一条起点最远的点作为下一跳的起点,这样每次都能跳到最远的地方,全局跳跃次数最少。
class Solution {
public:
int jump(vector<int>& nums) {
int nums_size = nums.size();
if (nums_size <= 1) return 0;
if (nums[0] >= nums_size) return 1;
int next_index = 0;
int rest_step = nums[0];
int cnt = 1; // 每次寻找下一跳都代表已经跳出了一步
int i = 0;
while (i + rest_step < nums_size) { //
int temp_rest = 0;
for (int j = 1; j <= rest_step; ++j) {
if (i + 1 + j >= nums_size) return cnt; // 如果当前点的可达范围已经可以到达最后一个点了,则结束
if (temp_rest < j + nums[i + j]) {
temp_rest = j + nums[i + j];
next_index = i + j;
}
}
cnt++; // 找到下一跳的起点,还没有到达最后一个点,则继续跳
i = next_index; // 从下一跳的起点开始
rest_step = nums[next_index]; // 下一跳的最长跳步数
}
return cnt;
}
};
自己写的有点麻烦,都快把自己绕进去了。看了卡哥的写法,茅塞顿开
由于题目说了一定可以到达最后一个点,那么我们限制点只能到达最后一个点的前一个点。
如果最后到达了倒数第二个点,刚好再跳一次,否则说明直接通过倒数第二个点前面的点就能到达。
class Solution {
public:
int jump(vector<int>& nums) {
int nums_size = nums.size();
int ans = 0;
int next_distance = 0;
int cur_distance = 0;
for (int i = 0; i < nums_size - 1; ++i) { // 限制当前只能移动到最后一个点的前一个点
next_distance = max(i + nums[i], next_distance); // 更新下一跳能到达的最远位置
if (i == cur_distance) { // 如果指针移动到当前点所能到达的最远处,则开始下一跳
cur_distance = next_distance; // 更新为下一跳结点所能到达的最远位置
ans++;
}
}
return ans;
}
};