122.买卖股票的最佳时机II
题目链接:买卖股票的最佳时机 II
如果想到其实最终利润是可以分解的,那么本题就很容易了!其实就是把利润分解为以每天为一个维度,我们可以只收集正利润的区间,获取正利润的区间就是股票买卖的区间,最终只需要总利润,不需知道每个区间。
// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
int maxProfit(vector<int>& prices) {
int ret = 0;
int sum = 0;
for (int i = 1; i < prices.size(); ++i)
{
sum = prices[i] - prices[i - 1];
if (sum > 0)
{
ret += sum;
}
}
return ret;
}
};
55. 跳跃游戏
题目链接:跳跃游戏
其实跳几步无所谓,关键在于可跳的覆盖范围!不一定非要明确一次究竟跳几步,每次取最大的跳跃步数,这个就是可以跳跃的覆盖范围。这个范围内,别管是怎么跳的,反正一定可以跳过来。那么这个问题就转化为跳跃覆盖范围究竟可不可以覆盖到终点!每次移动取最大跳跃步数(得到最大的覆盖范围),每移动一个单位,就更新最大覆盖范围。
// 时间复杂度: O(n)
// 空间复杂度: O(1)
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
题目链接:跳跃游戏 II
贪心的思路,局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一。整体最优:一步尽可能多走,从而达到最少步数。
真正解题的时候,要从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最少步数!这里需要统计两个覆盖范围,当前这一步的最大覆盖和下一步最大覆盖。如果移动下标达到了当前这一步的最大覆盖最远距离了,还没有到终点的话,那么就必须再走一步来增加覆盖范围,直到覆盖范围覆盖了终点。
这里还是有个特殊情况需要考虑,当移动下标达到了当前覆盖的最远距离下标时
- 如果当前覆盖最远距离下标不是是集合终点,步数就加一,还需要继续走。
- 如果当前覆盖最远距离下标就是是集合终点,步数不用加一,因为不能再往后走了。
// 时间复杂度: O(n)
// 空间复杂度: O(1)
class Solution {
public:
int jump(vector<int>& nums) {
if (nums.size() == 1) return 0;
int ret = 0; // 跳跃次数次数
int cur = 0; // 当前覆盖最远距离下标
int next = 0; // 下一步覆盖最远距离下标
for (int i = 0; i < nums.size(); ++i)
{
next = max(next, i + nums[i]);
if (i == cur) // 遇到当前最远距离下标
{
ret++; // 往后走一步
cur = next; // 更新最远距离
if (next >= nums.size() - 1)
break;
}
}
return ret;
}
};