文章目录
【买卖股票的最佳时机II】
思路:局部最优:收集每天的正利润,全局最优:求得最大利润。
c++
class Solution {
public:
int maxProfit(vector<int>& prices) {
int result = 0;
// 只收集每天正利润,局部最优得到全局最优
for(int i = 0; i < prices.size() - 1; i++){
int diff = prices[i + 1] - prices[i];
if(diff > 0){
result += diff;
}else continue;
}
return result;
}
};
【55.跳跃游戏】
思路:
-
跳几步无所谓,关键在于可跳的覆盖范围!
不一定非要明确一次究竟跳几步,每次取最大的跳跃步数,这个就是可以跳跃的覆盖范围。
这个范围内,别管是怎么跳的,反正一定可以跳过来。
-
那么这个问题就转化为跳跃覆盖范围究竟可不可以覆盖到终点!
每次移动取最大跳跃步数(得到最大的覆盖范围),每移动一个单位,就更新最大覆盖范围。
贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点。
c++
class Solution {
public:
bool canJump(vector<int>& nums) {
int cover = 0;
if (nums.size() == 1) return true; // 只有一个元素,就是能达到
for (int i = 0; i <= cover; i++) { // 注意这里是小于等于cover
cover = max(i + nums[i], cover);
if (cover >= nums.size() - 1) return true; // 说明可以覆盖到终点了
}
return false;
}
};
【跳跃游戏 II】
思路:还是覆盖范围,两个覆盖范围,一个curDistance判断,一个NextDistance更新
以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最少步数!
这里需要统计两个覆盖范围,当前这一步的最大覆盖和下一步最大覆盖。
如果移动下标达到了当前这一步的最大覆盖最远距离了,还没有到终点的话,那么就必须再走一步来增加覆盖范围,直到覆盖范围覆盖了终点。
c++
class Solution {
public:
int jump(vector<int>& nums) {
if(nums.size() == 1) return 0;
int curDistance = 0; // 当前覆盖最远距离下标
int ans = 0; // 记录走的最大步数
int nextDistance = 0; // 下一步覆盖最远距离下标
for(int i = 0; i < nums.size(); i++){
nextDistance = max(nextDistance, i + nums[i]);
if(i == curDistance){
ans++; // 需要走下一步
curDistance = nextDistance; // 更新当前覆盖最远距离下标
if(nextDistance >= nums.size() - 1) break;
}
}
return ans;
}
};
【1005.K次取反后最大化的数组和】
思路:两次贪心,别怕麻烦
- 第一步:将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
- 第二步:从前向后遍历,遇到负数将其变为正数,同时K--
- 第三步:如果K还大于0,那么反复转变数值最小的元素,将K用完
- 第四步:求和
c++
class Solution {
static bool cmp(int a, int b) {
return abs(a) > abs(b);
}
public:
int largestSumAfterKNegations(vector<int>& A, int K) {
sort(A.begin(), A.end(), cmp); // 第一步
for (int i = 0; i < A.size(); i++) { // 第二步
if (A[i] < 0 && K > 0) {
A[i] *= -1;
K--;
}
}
if (K % 2 == 1) A[A.size() - 1] *= -1; // 第三步
int result = 0;
for (int a : A) result += a; // 第四步
return result;
}
};