题目链接:122. 买卖股票的最佳时机 II - 力扣(LeetCode)
class Solution
{
public:
int maxProfit(vector<int> &prices)
{
int sum=0;
for(int i=0;i<prices.size()-1;i++){
sum+=max(prices[i+1]-prices[i],0);
}
return sum;
}
};
这就是贪心算法吗,虽然不是很明白,但是确实挺精妙的,其实一开始我按昨天的一个思路,找连续序列的最大值和最小值,写了挺多的if语句,很繁琐。
再看一下这个解答,惊了。还能这样!细想一下,可不就是这样吗,找相邻的正差值来相加,就是我们要求的了。算法题真的是越做越感觉我的思路太僵化了,真的不会灵活转换一下。
那么只收集正利润就是贪心所贪的地方!
局部最优:收集每天的正利润,全局最优:求得最大利润。
局部最优可以推出全局最优,找不出反例,试一试贪心!
class Solution
{
public:
bool canJump(vector<int> &nums)
{
if(nums.size()==1) return true;
int cover=0;
for(int i=0;i<=cover;i++){
if(cover<(nums[i]+i)) cover=i+nums[i];
if(cover>=nums.size()-1) return true;
}
return false;
}
};
一开始是想通过找0来解决,如果有一个0如何都不能跨越的话那么这就是false ,这是一个很只管的想法,只能说还是浅薄了点。
看了贪心算法,虽然想不出来什么贪心,但看了解答之后好像又觉得确实贪心。从局部到整体,想不出反例就试试贪心。确实有用。
每次取这个数的最大覆盖范围为cover,然后就逐个检查每个下标的最大覆盖范围有无大于cover,如果大于cover就更新,如果没有就不变。如此这样,知道cover大于这个数组的长度,所以就可以得出一个true;否则就是false.
题目链接:45. 跳跃游戏 II - 力扣(LeetCode)
class Solution
{
public:
int jump(vector<int> &nums)
{
if(nums.size()==1) return 0;
int nextDistance=0;
int curDistance=0;
int step=0;
for(int i=0;i<nums.size();i++){
nextDistance=max(i+nums[i],nextDistance);
if(i==curDistance){
curDistance=nextDistance;
step++;
if(curDistance>=nums.size()-1){
break;
}
}
}
return step;
}
};
真的难啊,不管是贪心还是不贪心,这种贪心的思路正常情况下我是写不出来的。
本质上是在遍历数组的同时找每一步的最大覆盖到的下标nextDistance , 一直比较nextDistance和nums[i]+i的大小,取最大的,就是说取能覆盖的最大范围。直到下标到curDistance的地方。这时候,让curDistance=nextDistance就行,然后让步数加一。
本质上这种解法和题目是差不多逻辑的。就是方法比较难想出来。如果新的i+nums[i]所能表示的坐标是远于当前的nextdistance的话,那么我们选择的就是这个nextdistance范围内所能取到的表示距离最远的那一个数。然后我们走到了curdistance的地方,也就是这一步的next distance所对应的地方,因为我们已经更新了nexdistance,所以就当作是在合理范围内走了一步,并选择了最好的下一步,然后我们就把我们已经选好的最远的下一步坐标的值赋给curdistance就行。