122. 买卖股票的最佳时机 II - 力扣(LeetCode)
思路:
1、在这自己采用双指针的方式,因为只需要判断当天的股票价格与第二天股票价格是否盈利,若盈利,就买,采用这种方式
2、若不盈利,就不够买此股票,就让当前慢指针指向第二天的股票值。
3,、若后面的股票一直都是在涨,就保持当前慢指针不动,一直让快指针向后移动,直到遇到开始亏钱,出现负盈利,再更新慢指针。
class Solution {
public:
int maxProfit(vector<int>& prices)
{
if (prices.size() <= 1)return 0;
int profit = 0;
int fast = 0;//用来判断当快指针是否到达最后一天了,若到达,说明,最后一天相对于前一天来说也是盈利的,要加上
int slow = 0;//慢指针
for (int i = 0; i < prices.size() - 1; i++)//要将最后一天留出来,这样避免代码超出空间
{
if (prices[i + 1] > prices[i])//如果第二天股票价格比当天价格高,就让快指针向后移动,并且fast用来记录第几天
{
fast = i + 1;
}
else//若不满足,就让慢指针指向第二天股票价格
{
profit += (prices[i] - prices[slow]);//因为满足不盈利了,说明第i天到slow还是盈利的,所以需要加上此利润
slow = i + 1;//让慢指针指向第二天
}
if (fast == prices.size() - 1)//这是用来判断是否处于最后一天,是否盈利,若等于,说明最后一天是盈利的,加上最后一天的盈利
{
profit += (prices[fast] - prices[slow]);
}
}
return profit;
}
};
在看完卡哥代码,才发现想复杂了,好的算法,真的想不到
卡哥思路是,判断第二天减去第一天价格是否大于0,若大于0 说明是盈利的,只要盈利就加上,依次向后走,直到遍历完整个数组,最后的盈利也就是最大盈利。
这里主要考虑的一个点便是,我可以当天卖掉我的股票,然后又买进来。这个总和是不变的。
int maxprofit(vector<int>& prices)
{
int result = 0;
for (int i = 0; i < prices.size(); i++)
{
result += max(prices[i] - prices[i - 1], 0);
}
return result;
}
思路;
因为是要判断是否能跳到最后一格,在这我们应该先分清
跳跃到达的位置应该是:数组下标+当前下标的值
若能够达到最后一个位置应该是:当前最大跳跃位置>=数组大小-1;
我们就可以在这里开始判段,因为每个小标的跳跃到达位置也就是可达到的范围
不断在此范围内,遍历,下标,选取能够到达的最大跳跃位置,判断是否满足条件即可。
并且这个遍历范围也是不断改变,是随着最大范围的变化而变化:
注意:在这不需要考虑是否会超出数组范围,因为一旦超出,就会跳出循环,不会往下面遍历。
class Solution {
public:
bool canJump(vector<int>& nums)
{
int cover = 0;//定义一个跳跃到达位置
if (nums.size() <= 1)return true;//若当前数组值小于等于1,说明已经达到
for (int i = 0; i <= cover; i++)//开始遍历
{
cover = max(i + nums[i], cover);//不断更新最大跳跃的范围
if (cover >= nums.size() - 1)return true;//只要一旦满足,就会退出循环,若不满足,cover值是小于数组长度,故不会越界。
}
return false;
}
};
说实话,这题比上题难多了,因为不知道如何确定我是否要跳一步,要想好久
解题思路:
根据上题,跳跃位置与能否达到最后一个位置是一样计算的。
这个跳跃位置也是要等于数组下标的,在这定义两个范围,一个就是在当前可用范围,另一个就是当前可用范围内的最大可覆盖范围。
int curCover=0;//当前可用范围,寻找范围
int nextCover=0;//当前可用范围内的最大范围
当我们遍历到当前下标值等于可用范围时,说明我们需要跳一下
因为当前可用范围就是我们能够在当前达到的最大范围,若已经到达最大范围还是没能够到达最后一个值,说明我们要往后面走一步,看看新的范围,
若在当前范围内,nextCover值大于数组长度,说明能够达到,我们直接跳出循环即可,若不能,就让当前范围,等于此范围内的最大范围值,更新此范围,向后走。
因为当处于0的阶段已经考虑进去,故代码符合逻辑。
并且若curCover不能往后面走了,当遍历完整个数组,也会返回一个值,就是0,说明不能通过跳跃达到后面。
也就是说我现在最大能调到的位置也就是不能达到最后。
注意:这里跳跃次数一定要写在判断条件之前。因为无论如何,我至少都是一次,只有满足之后我才不用跳。
class Solution {
public:
int jump(vector<int>& nums)
{
if (nums.size() == 1)return 0;
int curCover = 0;
int result = 0;
int nextCover = 0;//记录当前下一个的最大覆盖范围
for (int i = 0; i < nums.size(); i++)
{
nextCover = max(i + nums[i], nextCover);
if (i == curCover)
{
result++;
curCover = nextCover;
if (nextCover >= nums.size() - 1)break;
}
}
return result;
}
};