122.买卖股票的最佳时机
题目描述:
给你一个整数数组
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 * 1040 <= prices[i] <= 104
思路:
我们可以将每天单独的利润都计算出来,如果利润为正,则进行收集,如果利润为负,则进行抛弃,因此题目不需要我们记录哪天买入以及哪天卖出,所以直接进行结果收集即可,即如下图所示
代码如下:
int maxProfit(int* prices, int pricesSize) { int bonus = 0; for(int i = 1; i < pricesSize ; i++) { if(prices[i] - prices[i-1] < 0) continue; else bonus += prices[i] - prices[i-1]; } return bonus; }
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 <= 1040 <= nums[i] <= 105
思路:
我们不需要去追求具体是怎么跳的,我们只需要查看可以到达的数组元素的覆盖范围是多大即可(局部最优),只要可到达的覆盖范围超出我们数组的长度(全局最优),那么我们就一定可以到达数组的末尾位置,如果没有超出覆盖范围,则肯定到达不了,即如下图所示
我们可以使用一个变量来标记我们的覆盖范围,在这个覆盖范围内去跳跃,因为覆盖范围是不断变化的,因此我们需要进行比较,取出最大的覆盖范围
代码实现:
bool canJump(int* nums, int numsSize) { // 初始化覆盖范围为0 int cover = 0; // 如果数组长度为0,则可以直接到达终点,返回true if(numsSize == 0) return true; // 遍历数组中的每个位置 for(int i = 0; i <= cover ; i++) { // 更新覆盖范围:当前位置加上该位置能够跳跃的最远距离与当前覆盖范围的较大值 cover = i + nums[i] > cover ? i + nums[i] : cover; // 如果覆盖范围已经覆盖了数组的末尾位置,则可以到达终点,返回true if(cover >= numsSize - 1) return true; } // 如果遍历完整个循环还没有到达终点,则返回false 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 <= 1040 <= nums[i] <= 1000- 题目保证可以到达
nums[n-1]
思路:
我们不需要去追求具体是怎么跳的,我们只需要查看可以到达的数组元素的覆盖范围是多大即可,即使用最少的步数跳到最大的覆盖范围(局部最优),即每次我们跳转到一个新的覆盖范围时,又找到新覆盖范围内可以跳转的最大覆盖范围,再根据这个覆盖范围进行跳转
代码实现:
int jump(int* nums, int numsSize) { // 如果数组长度为1,无需跳跃,直接返回0步 if(numsSize == 1) return 0; // 初始化当前覆盖范围、下一次能覆盖的最远位置、跳跃步数为0 int cover = 0; int next = 0; int count = 0; // 遍历数组中的每个位置 for(int i = 0; i < numsSize ; i++) { // 更新下一次能够覆盖的最远位置 next = (i + nums[i]) > next ? i + nums[i] : next; // 如果当前位置达到了当前覆盖范围的边界 if(i == cover) { // 如果当前覆盖范围没有覆盖到数组末尾 if(cover != numsSize - 1) { // 增加跳跃步数 count++; // 更新当前覆盖范围为下一次能够覆盖的最远位置 cover = next; } } } // 返回跳跃步数 return count; }
文章讲述了如何在股票市场中寻找最佳买卖时机以获取最大利润,以及解决两种跳跃游戏问题(包括常规跳跃和跳跃游戏II)的算法策略,强调局部最优到全局最优的思考过程和代码实现。



765





