代码随想录算法训练营第三十二天|122.买卖股票的最佳时机II 、55. 跳跃游戏、45.跳跃游戏II
买卖股票的最佳时机II
122.买卖股票的最佳时机II
文章讲解:https://programmercarl.com/0122.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BAII.html
题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/
视频讲解:https://www.bilibili.com/video/BV1ev4y1C7na/
自己看到题目的第一想法
这个题目无法排序。
贪心算法思路:从局部最优推导出全局最优。
局部最优:短期利润最大化??
全局最优:??
没思路。
看完代码随想录之后的想法
利润可以分解,类似一种数学拆分的手段。
假如第0天买入,第3天卖出,那么利润为:prices[3] - prices[0]。
相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。
就是第三天买第四天卖 + 第二天买第三天卖 + 第一天买第二天卖
此时就是把利润分解为每天为单位的维度,而不是从 0 天到第 3 天整体去考虑。
把每天的利润算出之后,就可以把每天的正利润求和,得到最终最大利润。
看下图:4+5即为第二天买第四天卖,3即为第五天买第六天卖
public int maxProfit(int[] prices) {
int result = 0;
for(int i = 1; i < prices.length; i++){
int value = prices[i] - prices[i - 1];
if(value > 0){
result += value;
}
}
return result;
}
自己实现过程中遇到哪些困难
看了代码随想录的方法,代码实现就很简单。
跳跃游戏
55. 跳跃游戏
文章讲解:https://programmercarl.com/0055.%E8%B7%B3%E8%B7%83%E6%B8%B8%E6%88%8F.html
题目链接:https://leetcode.cn/problems/jump-game/
视频讲解:https://www.bilibili.com/video/BV1VG4y1X7kB/
自己看到题目的第一想法
局部最优:循环数组,判断有没有遇到0,遇到0的话判断前面的是否大于2。
全局最优:
想法一:这里走多和走少是一样的,因此直接就一步步走,计算最大长度即可。这个想法pass,无法跳过0。
想法二:这里只管往前走,遇到0就判断0前面的数字有没有大于0,如果遇到连续合并0则判断第一个0前的值是否大于0的数量。
看完代码随想录之后的想法
将问题转化为跳跃覆盖范围可不可以覆盖到终点。
即用最大的步长去遍历,遍历过程中取最大步长能走的步数的补充,增加可移动数。
如先用i去遍历,遍历能达到的最大值为cover,在遍历的过程中,动态变化cover的值。
自己实现过程中遇到哪些困难
自己实现没有什么问题,整体就是按照动态变化cover的值来做逻辑处理。
跳跃游戏II
45.跳跃游戏II
文章讲解:https://programmercarl.com/0045.%E8%B7%B3%E8%B7%83%E6%B8%B8%E6%88%8FII.html
题目链接:https://leetcode.cn/problems/jump-game-ii/
视频讲解:https://www.bilibili.com/video/BV1Y24y1r7XZ/
自己看到题目的第一想法
循环的过程中,只要出现加一次大于结尾的 就直接返回。
改变cover的值,每次改变完cover则变化count的值。
看完代码随想录之后的想法
定义3个局部变量,当前覆盖范围 cur 下一个覆盖范围 next 和结果result。
for循环,每走一步就会变化next的范围,取最大的next值。假如i到cur的位置了,并且cur不为末尾位置。则result++,走一步取下一个最大范围。修改cur的值。
贪心的思路,局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一。整体最优:一步尽可能多走,从而达到最少步数。
所以真正解题的时候,要从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最少步数!
这里需要统计两个覆盖范围,当前这一步的最大覆盖和下一步最大覆盖。
自己实现过程中遇到哪些困难
按照代码随想录的思路完成了代码
if(nums.length == 1)return 0;
// 循环的过程中,只要出现加一次大于结尾的 就直接返回
int cur = 0;
int next = 0;
int result = 0;
for(int i = 0; i < nums.length; i++){
next = Math.max(i + nums[i],next);
if(cur == i){
// 说明到位置了,需要再走一步了
if(cur < nums.length){
result++;
cur = next;
}
if(cur >= nums.length - 1){
return result;
}
}
}
return result;
今日收获&学习时长
贪心算法的答案一般比较难想到。
学习时长:
1h30min