122. 买卖股票的最佳时机 II
给你一个整数数组
prices
,其中prices[i]
表示某支股票第i
天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
示例 1:
输入:prices = [7,1,5,3,6,4] 输出:7 解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。总利润为 4 + 3 = 7 。示例 2:
输入:prices = [1,2,3,4,5] 输出:4 解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。总利润为 4 。示例 3:
输入:prices = [7,6,4,3,1] 输出:0 解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。提示:
1 <= prices.length <= 3 * 104
0 <= prices[i] <= 104
状态:完成,我的代码太蠢了
思路:看carl的代码恍然大悟了,一开始我就想着跟上一题一样求谷值峰值然后把两个减法,其实可以不用这样子,可以把利润拆分,只要前后两天的利润是正的说明就在赚钱了,局部的最佳这题就是全局的最佳。
蠢代码:
class Solution {public int maxProfit(int[] prices) {int maxBouns=0;Stack<Integer> stack=new Stack<>();int type=-1;stack.add(prices[0]);for(int i=1;i<prices.length;i++){if(type<0){if(stack.peek()>prices[i]){stack.pop();stack.add(prices[i]);}else{type=1;stack.add(prices[i]);}}else{if(stack.peek()<prices[i]){stack.pop();stack.add(prices[i]);}else{type=-1;stack.add(prices[i]);}}}if(type==-1){stack.pop();}int size=stack.size();for(int i=0;i<size/2;i++){int max=stack.pop(); int min=stack.pop();maxBouns+=max-min;}return maxBouns;}
}
帅气代码:
class Solution {public int maxProfit(int[] prices) {int maxBouns=0;for(int i=1;i<prices.length;i++){maxBouns+=Math.max(prices[i]-prices[i-1],0);}return maxBouns;}
}
55. 跳跃游戏
给你一个非负整数数组
nums
,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标,如果可以,返回
true
;否则,返回false
。示例 1:
输入:nums = [2,3,1,1,4] 输出:true 解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。示例 2:
输入:nums = [3,2,1,0,4] 输出:false 解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。提示:
1 <= nums.length <= 104
0 <= nums[i] <= 105
状态:完成
思路:该题关键就是看目前最多能覆盖到哪里,他最多能覆盖到哪里我们就只能走到哪里。
class Solution {public boolean canJump(int[] nums) {if(nums.length==1) return true;int max=0;for(int i=0;i<=max;i++){nums[i]=nums[i]+i;max=Math.max(nums[i],max);if(nums[i]>=nums.length-1) return true;}return false;}
}
45. 跳跃游戏 II
给定一个长度为
n
的 0 索引整数数组nums
。初始位置为nums[0]
。每个元素
nums[i]
表示从索引i
向前跳转的最大长度。换句话说,如果你在nums[i]
处,你可以跳转到任意nums[i + j]
处:
0 <= j <= nums[i]
i + j < n
返回到达
nums[n - 1]
的最小跳跃次数。生成的测试用例可以到达nums[n - 1]
。示例 1:
输入: nums = [2,3,1,1,4] 输出: 2 解释: 跳到最后一个位置的最小跳跃数是2
。从下标为 0 跳到下标为 1 的位置,跳1
步,然后跳3
步到达数组的最后一个位置。示例 2:
输入: nums = [2,3,0,1,4] 输出: 2提示:
1 <= nums.length <= 104
0 <= nums[i] <= 1000
- 题目保证可以到达
nums[n-1]
状态:没做出来,看了之前的笔记做出来了
该题我使用贪心算法去做,我先做了55跳跃游戏,再做这个跳跃游戏二。这两题看上去可能差不多,其实差别挺大的我感觉,一个是判断能不能跳到,就只要知道他的最大覆盖范围是不是大于或等于这个数组的长度就行了,这个45题前提是肯定能跳到,求跳到最后一格的最短跳跃次数。
要求跳的最短次数,所以贪心的策略就是跳最大的距离。跳跃次数增加的前提就是,节点移动到了上一个最大的覆盖距离。为什么呢?
我们一步一步地移动节点,在第一步的时候一步一步地可以求出这一步的最大覆盖距离,到了上一步最大覆盖距离的点的时候,还没有走完,所以步数要加一,然后就要看看这一步最多可以移动到哪里,如果可以覆盖整个数组则不用继续循环了,因为在这一步的循环中就可以到最后。
太巧妙了贪心。
class Solution {public int jump(int[] nums) {if(nums.length==1) return 0;int max=0;int preMax=0;int count=0;for(int i=0;i<=max;i++){max=Math.max(max,nums[i]+i);if(i==preMax){count++;preMax=max;if(max>=nums.length-1) return count;}}return count;}
}
感想:贪心已经过半,准备迎接动态规划🤭。