首页 > 编程语言 >代码随想录算法Day32 | 122.买卖股票的最佳时机II ,55. 跳跃游戏 ,45.跳跃游戏II

代码随想录算法Day32 | 122.买卖股票的最佳时机II ,55. 跳跃游戏 ,45.跳跃游戏II

时间:2023-03-04 14:56:24浏览次数:58  
标签:游戏 nums int II prices length 跳跃 覆盖范围 dp

把利润分解为每天为单位的维度,而不是从0天到第3天整体去考虑!122.买卖股票的最佳时机II

题目链接:122. 买卖股票的最佳时机 II - 力扣(LeetCode)

思路

 

 

 这道题使用贪心算法思路为:把利润分解为每天为单位的维度,而不是从0天到第3天整体去考虑!

将数据画成折现图

 

根据图中可以很明显看出我们只收集正利润即可 。得到的数组如下。

 

 

局部最优:收集每天的正利润,全局最优:求得最大利润。

代码

1 // 贪心思路
2 class Solution {
3     public int maxProfit(int[] prices) {
4         int result = 0;
5         for (int i = 1; i < prices.length; i++) {
6             result += Math.max(prices[i] - prices[i - 1], 0);
7         }
8         return result;
9     }
 1 class Solution { // 动态规划
 2     public int maxProfit(int[] prices) {
 3         // [天数][是否持有股票]
 4         int[][] dp = new int[prices.length][2];
 5 
 6         // base case
 7         dp[0][0] = 0;
 8         dp[0][1] = -prices[0];
 9 
10         for (int i = 1; i < prices.length; i++) {
11             // dp公式
12             dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
13             dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
14         }
15 
16         return dp[prices.length - 1][0];
17     }
18 }

55. 跳跃游戏

题目链接:55. 跳跃游戏 - 力扣(LeetCode)

思路

这道题关键在于可跳的范围,我们不一定非要明确一次究竟跳几步,每次取最大的跳跃步数,这个就是可以跳跃的覆盖范围。

那么这个问题就转化为跳跃覆盖范围究竟可不可以覆盖到终点!

每次移动取最大跳跃步数(得到最大的覆盖范围),每移动一个单位,就更新最大覆盖范围。

贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点。

可以参考下图方便理解。

 

 

代码

 1 class Solution {
 2     public boolean canJump(int[] nums) {
 3         if (nums.length == 1) {
 4             return true;
 5         }
 6         //覆盖范围, 初始覆盖范围应该是0,因为下面的迭代是从下标0开始的
 7         int coverRange = 0;
 8         //在覆盖范围内更新最大的覆盖范围
 9         for (int i = 0; i <= coverRange; i++) {
10             coverRange = Math.max(coverRange, i + nums[i]);
11             if (coverRange >= nums.length - 1) {
12                 return true;
13             }
14         }
15         return false;
16     }
17 }

 

45.跳跃游戏II

题目链接:45. 跳跃游戏 II - 力扣(LeetCode)

思路

这道题贪心的思路为:局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一。整体最优:一步尽可能多走,从而达到最小步数。

解题时从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最小步数!

这里需要统计两个覆盖范围,当前这一步的最大覆盖和下一步最大覆盖。

 

 

图中覆盖范围的意义在于,只要红色的区域,最多两步一定可以到!(不用管具体怎么跳,反正一定可以跳到)

代码

方法一

 1 // 版本一
 2 class Solution {
 3     public int jump(int[] nums) {
 4         if (nums == null || nums.length == 0 || nums.length == 1) {
 5             return 0;
 6         }
 7         //记录跳跃的次数
 8         int count=0;
 9         //当前的覆盖最大区域
10         int curDistance = 0;
11         //最大的覆盖区域
12         int maxDistance = 0;
13         for (int i = 0; i < nums.length; i++) {
14             //在可覆盖区域内更新最大的覆盖区域
15             maxDistance = Math.max(maxDistance,i+nums[i]);
16             //说明当前一步,再跳一步就到达了末尾
17             if (maxDistance>=nums.length-1){
18                 count++;
19                 break;
20             }
21             //走到当前覆盖的最大区域时,更新下一步可达的最大区域
22             if (i==curDistance){
23                 curDistance = maxDistance;
24                 count++;
25             }
26         }
27         return count;
28     }
29 }

方法二

 1 // 版本二 (版本一的简化)
 2 class Solution {
 3     public int jump(int[] nums) {
 4         int result = 0;
 5         // 当前覆盖的最远距离下标
 6         int end = 0;
 7         // 下一步覆盖的最远距离下标
 8         int temp = 0;
 9         for (int i = 0; i <= end && end < nums.length - 1; ++i) {
10             temp = Math.max(temp, i + nums[i]);
11             // 可达位置的改变次数就是跳跃次数
12             if (i == end) {
13                 end = temp;
14                 result++;
15             }
16         }
17         return result;
18     }
19 }

 

标签:游戏,nums,int,II,prices,length,跳跃,覆盖范围,dp
From: https://www.cnblogs.com/xpp3/p/17178285.html

相关文章