代码随想录算法训练营第24天|122.买卖股票的最佳时机 II、55. 跳跃游戏、45.跳跃游戏 II、1005. K 次取反后最大化的数组和

LeetCode24

2025-02-24 21:14:17 星期一

题目描述:力扣24
文档讲解:代码随想录(programmercarl)122.买卖股票的最佳时机 II
视频讲解:《代码随想录》算法视频公开课:贪心算法也能解决股票问题!LeetCode:122.买卖股票最佳时机 II

代码随想录视频内容简记

这个题的局部最优就是去寻找每一天价格的差值,如果是正值,那么就选,这样求得得全部最优就是收获的利润最大化

注意:

这个题和53最大子数组和有点像,但是有不一样的地方就是53是算的之前加起来的所有和是不是正值,而24买卖股票算的是每一天的差值是不是正值

LeetCode测试

点击查看代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int result = 0;
        for (int i = 1; i < prices.size(); i++) {
            result += max(prices[i] - prices[i - 1], 0);
        }
        return result;
    }
};

LeetCode55

题目描述:力扣55
文档讲解:代码随想录(programmercarl)55. 跳跃游戏
视频讲解:《代码随想录》算法视频公开课:贪心算法,怎么跳跃不重要,关键在覆盖范围 | LeetCode:55.跳跃游戏

错误思路

刚开始写的代码是这样的,想着遍历一边数组,只要有一个能覆盖终点就可以,但是事实不是这样的,搞错了。

bool canJump(vector<int>& nums) {
	if (nums.size() == 1) return true;
	for (int i = 0; i < nums.size() - 1; i++) {
		if (nums.size() - 1 - i <= nums[i]) return true;
	}
	return false;
}

有一个用例是这样的,第一步就跳不过去,所以还是得用k哥cover的概念

正确思路

按照贪心的思路,局部最优就是每遍历一个元素,就取当前能覆盖到的最大范围,那么全局最优就是最后整个序列所能取到的最大覆盖范围

大致代码内容

点击查看代码
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 = max(cover, i + nums[i]);
            if (cover >= nums.size() - 1) return true;
        }
        return false;
    }
};

LeetCode45

题目描述:力扣45
文档讲解:代码随想录(programmercarl)45.跳跃游戏 II
视频讲解:《代码随想录》算法视频公开课:贪心算法,最少跳几步还得看覆盖范围 | LeetCode: 45.跳跃游戏 II

代码随想录视频内容简记

这道题的和55跳跃游戏的不同就在于这里要输出跳到终点所需要的最少步数

这道题目贪的局部最优也是一个局部的最长步数,全局最优就是最后能覆盖到重点的最少步数

梳理

  1. 首先定义一个next,这个用来表示下一步的覆盖范围,但是这个next是不是之后真正下一步跳跃的起点(图中的3),还不能确定,因为在遍历的时候需要记录最大值。所以必须得把当前的覆盖范围遍历完之后才能确定。
  1. 图中的3用cur来表示当前跳跃的起始。

  2. 这里有一个小细节,为了避免在遍历完一个数的覆盖范围之后(比如第一个数2的覆盖范围是2,会遍历到1),从一般常识来讲,他需要重新回到3开始下一步的跳跃,按照我的想法,是应该同时把3的索引和他的值用max记录下来之后再做判断。这里就不对

    覆盖范围的定义:当前索引+跳跃距离

    只有同时记录每一个数的索引和跳跃距离之和才行。

LeetCode测试

注意这个题有一个小细节,特意看了一下,为什么for循环中不再是cover了呢?因为力扣中明确说了

题目保证可以到达 nums[n-1]

点击查看代码
class Solution {
public:
    int jump(vector<int>& nums) {
        int next = 0, cur = 0, result = 0;
        if (nums.size() == 1) return 0;
        for (int i = 0; i < nums.size(); i++) {
            next = max(nums[i] + i, next);
            if (i == cur) {// 表示遍历完第一步
                if (cur != nums.size() - 1) {// 表示cur没有遍历到最后一个数
                    result++;
                    cur = next;
                } else {// 表示已经遍历到最后一个数
                    break;
                }
            }
        }
        return result;
    }
};

LeetCode1005

题目描述:力扣1005
文档讲解:代码随想录(programmercarl)1005. K 次取反后最大化的数组和
视频讲解:《代码随想录》算法视频公开课:贪心算法,这不就是常识?还能叫贪心?LeetCode:1005.K次取反后最大化的数组和

代码随想录视频内容简记

这道题有两个贪心策略,第一个贪心的局部最优就是把所有具有最大绝对值的负数优先取反,使其变成正数,第二个局部最优就是把最小的正数进行重复取反。两个局部最优的全局最优都是取得最大的数组和

注意

在代码中有一个小细节,if (k % 2 == 1) nums[nums.size() - 1] *= -1;这里直接判断奇偶性来对最后的数进行处理,而不是用while循环一次次乘-1

LeetCode测试

点击查看代码
class Solution {
private:
    static bool cmp(int a, int b) {
        return abs(a) > abs(b);
    }
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        int result = 0;
        sort(nums.begin(), nums.end(), cmp);
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] < 0 && k > 0) {
                nums[i] *= -1;
                k--;
            }
        }
        if (k % 2 == 1) nums[nums.size() - 1] *= -1;
        for (int i = 0; i < nums.size(); i++) {
            result += nums[i];
        }
        return result;
    }
};
posted on   bnbncch  阅读(745)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示