1.题目链接:122. 买卖股票的最佳时机 II
题目描述:
给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润
解法:
1.此题全局最优解是获得最大利润,那么我要找到局部最优解。
2.我们可以这样想,prices[3] - prices[0] = prices[3] - prices[2] + prices[2] - prices[1] +prices[1] - prices[0]。即将其表示成每一天的利润。那么只要利润是正数,就对总利润起增大的作用,如果小于0就起减少的作用。所以就收集正数就行。
3.定义result用于收集最大利润。
4.从i = 1开始遍历,因为我们要先买再卖。
5.result += max.(nums[i] - nums[i-1], 0);
6.最后返回result即可。
下面为代码(java):
2.题目链接:55. 跳跃游戏
题目描述:
给定一个非负整数数组 nums
,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
解法:
1.判断是否可以到达最后一个下标,那么我们要将此题想成覆盖范围的问题,而不是判断到哪个位置下一步该跳几部,这样就会很容易想到。
2.那么要声明一个cover = 0,表示覆盖范围。我们要在覆盖范围内遍历才是有效的。
3.cover = max.(cover, i+nums[i]);即在覆盖范围内求最大的覆盖范围是多少。
4.if(cover >= nums.length -1){return true;}
5.整个循环都遍历完了,都没有返回true就返回false。
6.最后要考虑特殊情况,如果只有一个元素的话肯定可以跳到,因为最开始就指到第一个元素。
下面为代码(java):
3.题目链接: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.此题全局最优解是求最小跳跃次数,那么局部最优解就是要每次尽可能的向前跳,依旧用覆盖范围的思想来思考问题。
2.定义当前覆盖范围 cur,定义下一次的覆盖范围 next,定义跳跃次数 result
3.遍历整个数组,而不是在覆盖范围内遍历,这是此题和上题不同之处,因为此题有两个覆盖范围,我们之所以遍历整个数组是因为当我们遍历的指针指向cur的时候,说明当前覆盖范围遍历完了,然后看其和nums.length-1的关系,再决定是否进行下一次遍历。
4.即for(int i = 0;i < nums.length.i++){
next = max.(i+nums[i],next) // 因为我们在当前覆盖范围内找到下一次的覆盖范围,我们要做的是每一次尽可能多的向前跳,所以我们求下一次覆盖范围的时候要取最大值。
if(i == cur){// 判断当遍历到当前覆盖范围的时候,这里保证的就是上面的在当前覆盖范围内找下一次的覆盖范围。因为到i = cur的时候就开始判断了,所以next此时就收集了覆盖范围内的下一次覆盖范围。
if(cur < nums.length -1){//即当前覆盖范围没有跳到末尾,就要开启下次覆盖
result++;
cur = next;
if(cur >= nums.length - 1){break;}// 即如果下一次的覆盖范围到了末尾,直接跳出,就求得了最小步数。
}else{break;如果当前覆盖已经跳到末尾了,不用开启下次覆盖,直接跳出就得到了最小步数。
}
5.最后return result
6.同时要考虑特殊情况,如果数组长度就为1的话,那不用跳,直接次数就是0.
下面为代码(java):
4.总结:
①第一题:全局变量求最大利润,首先将每天的利润表示出来,然后只求正的利润---就是局部最优解。
②第二题:跳跃问题,用覆盖的思想来思考,在覆盖范围内遍历,然后更新覆盖范围,看其是否能覆盖到数组末尾。
③第三题:跳跃问题求最小次数---全局变量,局部变量---每次尽量向前跳。同样用覆盖的思想来解决。在整个数组范围内遍历,更新next的覆盖范围。同时要判断,当遍历到当前覆盖范围的时候,覆盖范围和整个数组长度的关系,如果不够就要开启下一次覆盖---即更新跳跃步数,更新cur,然后再判断cur和数组长度关系。如果够了,直接跳出,不用开启下次覆盖。