今天的题目还是感觉有难度,前三道题都想不出来思路,直接看讲解去了。。。贪心的难题真的好难想出来。
122.买卖股票的最佳时机II
这道题用贪心解很巧妙。涉及到一个数学技巧,从第i天买入,第j天卖出,所获得的利润为prices[j] - pricees[i],这个可以裂项为(prices[j] - prices[j - 1]) + (prices[j - 1] - prices[j - 2] )+ …+ prices[i + 1] - prices[i],要使总利润尽可能地大,肯定要让中间的每个小括号中的值为正数,不能为负数,所以遍历prices数组时统计当前位置与前一个位置的元素之差,如果为正则将这个差加入到结果中,就是让每一天相对于前一天的利润为正即可。
class Solution {
public:int maxProfit(vector<int>& prices) {int result = 0;for(int i = 1; i < prices.size(); i++){if(prices[i] - prices[i - 1] > 0)result += (prices[i] - prices[i - 1]);}return result;}
};
55. 跳跃游戏
这道题目确实是想不出来,看完讲解后感觉确实巧妙,本题的核心就在于不断地维护从起点出发,经过若干次跳跃后所能达到的最远距离,如果最远距离达到了数组末端则直接return true,否则循环结束后返回false,另外,循环的结束条件不应该是i到达数组末端,因为有些情况的数组根本达不到末端,i到达最大覆盖范围的边缘就应该结束循环。
class Solution {
public:bool canJump(vector<int>& nums) {int cover = 0;for(int i = 0; i <= cover; i++){cover = max(i + nums[i], cover); //cover始终维护从起点出发所能达到的最大范围if(cover >= nums.size() - 1)return true;}return false;}
};
45.跳跃游戏II
有了上一道题的基础依然做不出这道题。。。无语。。这道题比上一道题复杂很多,题目保证所给的数组都能跳到末尾,所以我们需要考虑用最少的步数跳到终点,这道题也是需要用next来维护最远距离,由于这道题一定能跳到终点,所以循环的终止条件就是i < nums.size(),用current记录当前位置,next即为下一次跳跃的目的地,当i追上current时,我们就需要进行下一次跳跃,然后current移动到next的位置上,next的更新方式与上一题相同。
class Solution {
public:int jump(vector<int>& nums) {int result = 0;int current = 0;int next = 0;for(int i = 0; i < nums.size(); i++){next = max(next, i + nums[i]); //更新维护最大覆盖范围if(i == current){ //已经遍历到当前的最大覆盖范围边缘if(i != nums.size() - 1){result++;current = next;if(current >= nums.size() - 1) //移动到数组尽头break;}else break;}}return result;}
};
1005.K次取反后最大化的数组和
这道题目比较简单,就是总共循环k次,每次循环中都将数组中的最小值取反(因为只有将最小值取反才能保证给总和带来的损失是最小的),循环结束后计算数组中元素总和返回即可。
class Solution {
public:int largestSumAfterKNegations(vector<int>& nums, int k) {while(k > 0){auto minIt = min_element(nums.begin(), nums.end());(*minIt) *= -1;k--;}return accumulate(nums.begin(), nums.end(), 0);}
};
贪心尊嘟好难!!