代码随想录Day 28|题目:122.买卖股票的最佳时机Ⅱ、55.跳跃游戏、45.跳跃游戏Ⅱ、1005.K次取反后最大化的数组和

提示:DDU,供自己复习使用。欢迎大家前来讨论~

文章目录

  • 题目
    • 题目一:122.买卖股票的最佳时机 II
      • 贪心算法:
      • 动态规划
    • 题目二:55.跳跃游戏
      • 解题思路:
    • 题目三: 45.跳跃游戏 II
      • 解题思路
      • 方法一
      • 方法二
    • 题目四:1005.K次取反后最大化的数组和
      • 解题思路
  • 总结

贪心算法继续刷题

题目

题目一:122.买卖股票的最佳时机 II

122. 买卖股票的最佳时机 II

  1. 贪心策略:一种直观的贪心策略是,当你发现股票价格比之前低时买入,在价格比买入时高时卖出,然后重复这个过程。这种策略基于一个简单的假设:如果当前价格比之前低,那么未来有可能会涨;如果当前价格比买入时高,那么现在卖出可以获利。
  2. 分解问题:这里的“分解问题”意味着你将整个问题分解为多个小问题。在股票买卖问题中,可以将问题分解为多个独立的买卖对。每个买卖对都独立于其他对,只考虑买入点和卖出点之间的差额。
  3. 贪心选择:在每个独立的买卖对中,选择当前的最低点作为买入点,然后选择之后的第一个高点作为卖出点。这样做是因为在贪心算法中,我们总是希望在成本最低时买入,在利润最高时卖出。
  4. 循环反复:这个过程可以在整个股票价格序列上重复进行。每次找到一个买入点和卖出点后,就将这两个点之间的差额加到总利润中,然后继续寻找下一个买入点。
  5. 算法效率:这种方法的效率相对较高,因为它只需要遍历一次股票价格序列,每次找到买入点和卖出点后就可以计算出一部分利润。

贪心算法:

这道题目可能我们只会想,选一个低的买入,再选个高的卖,再选一个低的买入…循环反复。

如果想到其实最终利润是可以分解的,那么本题就很容易了!

如何分解呢?

假如第 0 天买入,第 3 天卖出,那么利润为:prices[3] - prices[0]。

相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。

此时就是把利润分解为每天为单位的维度,而不是从 0 天到第 3 天整体去考虑!

那么根据 prices 可以得到每天的利润序列:(prices[i] - prices[i - 1])…(prices[1] - prices[0])。

122.买卖股票的最佳时机II

从图中可以发现,其实我们需要收集每天的正利润就可以,收集正利润的区间,就是股票买卖的区间,而我们只需要关注最终利润,不需要记录区间

那么只收集正利润就是贪心所贪的地方!

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

局部最优可以推出全局最优,找不出反例,试一试贪心!

完整的C++代码如下:

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;}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

动态规划

代码如下:

class Solution {
public:int maxProfit(vector<int>& prices) {// dp[i][1]第i天持有的最多现金// dp[i][0]第i天持有股票后的最多现金int n = prices.size();vector<vector<int>> dp(n, vector<int>(2, 0));dp[0][0] -= prices[0]; // 持股票for (int i = 1; i < n; i++) {// 第i天持股票所剩最多现金 = max(第i-1天持股票所剩现金, 第i-1天持现金-买第i天的股票)dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);// 第i天持有最多现金 = max(第i-1天持有的最多现金,第i-1天持有股票的最多现金+第i天卖出股票)dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);}return max(dp[n - 1][0], dp[n - 1][1]);}
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

小结:

股票问题其实是一个系列的,属于动态规划的范畴。

在一些情况下,贪心往往比动态规划更巧妙,更好用,所以别小看了贪心算法

本题中理解利润拆分是关键点! 不要整块的去看,而是把整体利润拆为每天的利润。

一旦想到这里了,很自然就会想到贪心了,即:只收集每天的正利润,最后稳稳的就是最大利润了。

题目二:55.跳跃游戏

55. 跳跃游戏

解题思路:

其实跳几步无所谓,关键在于可跳的覆盖范围!

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

这个范围内,别管是怎么跳的,反正一定可以跳过来。

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

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

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

img

i 每次移动只能在 cover 的范围内移动,每移动一个元素,cover 得到该元素数值(新的覆盖范围)的补充,让 i 继续移动下去。

而 cover 每次只取 max(该元素数值补充后的范围, cover 本身范围)。

如果 cover 大于等于了终点下标,直接 return true 就可以了。

class Solution {
public:bool canJump(vector<int>& nums) {int cover = 0;if (nums.size() == 1) return true; // 只有一个元素,就是能达到for (int i = 0; i <= cover; i++) { // 注意这里是小于等于covercover = max(i + nums[i], cover);if (cover >= nums.size() - 1) return true; // 说明可以覆盖到终点了}return false;}
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

题目三: 45.跳跃游戏 II

[45. 跳跃游戏 II](https://leetcode.cn/problems/letter-combinations-of-a-phone-number/)

解题思路

本题要计算最少步数,那么就要想清楚什么时候步数才一定要加一呢?

贪心的思路,局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一。

整体最优:一步尽可能多走,从而达到最少步数。

需要统计两个覆盖范围,当前这一步的最大覆盖和下一步最大覆盖:如果移动下标达到了当前这一步的最大覆盖最远距离了,还没有到终点的话,那么就必须再走一步来增加覆盖范围,直到覆盖范围覆盖了终点。

45.跳跃游戏II

图中覆盖范围的意义在于,只要红色的区域,最多两步一定可以到!

方法一

从图中可以看出来,就是移动下标达到了当前覆盖的最远距离下标时,步数就要加一,来增加覆盖距离。最后的步数就是最少步数。

这里还是有个特殊情况需要考虑,当移动下标达到了当前覆盖的最远距离下标时

  • 如果当前覆盖最远距离下标不是是集合终点,步数就加一,还需要继续走。
  • 如果当前覆盖最远距离下标就是是集合终点,步数不用加一,因为不能再往后走了。

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(nums[i] + i, nextDistance);  // 更新下一步覆盖最远距离下标if (i == curDistance) {                         // 遇到当前覆盖最远距离下标ans++;                                  // 需要走下一步curDistance = nextDistance;             // 更新当前覆盖最远距离下标(相当于加油了)if (nextDistance >= nums.size() - 1) break;  // 当前覆盖最远距到达集合终点,不用做ans++操作了,直接结束}}return ans;}
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

方法二

依然是贪心,思路和方法一差不多,代码可以简洁一些。

针对于方法一的特殊情况,可以统一处理,即:移动下标只要遇到当前覆盖最远距离的下标,直接步数加一,不考虑是不是终点的情况。

想要达到这样的效果,只要让移动下标,最大只能移动到 nums.size - 2 的地方就可以了。

因为当移动下标指向 nums.size - 2 时:

  • 如果移动下标等于当前覆盖最大距离下标, 需要再走一步(即 ans++),因为最后一步一定是可以到的终点。(题目假设总是可以到达数组的最后一个位置),如图:

  • 45.跳跃游戏II2
  • 如果移动下标不等于当前覆盖最大距离下标,说明当前覆盖最远距离就可以直接达到终点了,不需要再走一步。如图:

    45.跳跃游戏II1

    代码如下:

    // 版本二
    class Solution {
    public:int jump(vector<int>& nums) {int curDistance = 0;    // 当前覆盖的最远距离下标int ans = 0;            // 记录走的最大步数int nextDistance = 0;   // 下一步覆盖的最远距离下标for (int i = 0; i < nums.size() - 1; i++) { // 注意这里是小于nums.size() - 1,这是关键所在nextDistance = max(nums[i] + i, nextDistance); // 更新下一步覆盖的最远距离下标if (i == curDistance) {                 // 遇到当前覆盖的最远距离下标curDistance = nextDistance;         // 更新当前覆盖的最远距离下标ans++;}}return ans;}
    };
    
    • 时间复杂度: O(n)
    • 空间复杂度: O(1)

题目四:1005.K次取反后最大化的数组和

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;}
};
  • 时间复杂度: O(nlogn)
  • 空间复杂度: O(1)

小结:

本题其实很简单,不会贪心算法的同学都可以做出来,但是我还是全程用贪心的思路来讲解。

因为贪心的思考方式一定要有!

如果没有贪心的思考方式(局部最优,全局最优),很容易陷入贪心简单题凭感觉做,贪心难题直接不会做,其实这样就锻炼不了贪心的思考方式了。所以明知道是贪心简单题,也要靠贪心的思考方式来解题,这样对培养解题感觉很有帮助。


总结

  • 简单题目使用贪心算法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/52812.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙开发入门day15-焦点事件

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;还请三连支持一波哇ヾ(&#xff20;^∇^&#xff20;)ノ&#xff09; 目录 焦点事件 基础概念与规范 基础概念 走焦规范 走焦算法 获焦/失…

【逐行注释】MATLAB下的UKF(无迹卡尔曼滤波),带丰富的中文注释,可直接复制到MATLAB上运行,无需下载

文章目录 程序组成部分完整代码运行结果主要模块解读:运动模型绘图部分误差统计特性输出程序组成部分 由模型初始化、运动模型、UKF主体部分、绘图代码和输出部分组成: 完整代码 将下列代码复制粘贴到MATLAB里面,即可运行: % 三维状态量的UKF例程 % 作者联系方式:微信…

安全面试常见问题任意文件下载

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 1.1 任意文件下…

培训第三十九天(了解docker-compose,docker-compose编排容器,配置harbor服务)

一、回顾 1、拉取私有仓库镜像 # 配置dockerdocker pull 10.0.0.10:5000/centosnginx:v0 2、容器网络类型 brideg(net) default# docker启动之后会生成新的虚拟网卡&#xff0c;网卡的名称docker0# 网段默认是172.17.0.1# 所有的容器都桥接docker0&#xff0c;通过桥接共享网…

LRN正则化是什么?

LRN正则化&#xff0c;全称为Local Response Normalization&#xff08;局部响应归一化&#xff09;&#xff0c;是一种在深度学习&#xff0c;特别是在卷积神经网络&#xff08;CNN&#xff09;中常用的正则化技术。该技术旨在通过模拟生物视觉系统中的侧抑制现象&#xff0c;…

OpenLayers3, 设置地图背景

文章目录 一、前言二、代码实现三、总结 一、前言 本文基于OpenLayers3&#xff0c;实现地图加入背景图的功能。 二、代码实现 <!DOCTYPE html> <html xmlns"http://www.w3.org/1999/xhtml"> <head><meta http-equiv"Content-Type"…

QT学习ubuntu qt + desktop

环境搭建 ubuntu 安装QT 遇到kit 选择不了 通过sudo apt-get install qt5-default去安装SDK的时候报错&#xff1a; Package qt5-default is not available, but is referred to by another package. This may mean that the package is missing, has been obsoleted, or is …

Linux——nginx 负载均衡

常规的web服务器一般提供对于静态资源的访问&#xff0c;比如说&#xff1a;图片、web样式 网站提供的大部分交互功能都需要web编程语言的支持&#xff0c;而web服务对于程序的调用&#xff0c;不管编译型语言还是解释型语言&#xff0c;web服务同将对于应用程序的调用递交给通…

在蓝桥云课ROS中快速搭建Arduino开发环境

普通方式 一步步慢悠悠的搭建和讲解需要5-6分钟&#xff1a; 如何在蓝桥云课ROS中搭建Arduino开发环境 视频时间&#xff1a;6分40秒 高效方式 如何高效率在蓝桥云课ROS中搭建Arduino开发环境 视频时间&#xff1a;1分45秒 配置和上传程序到开发板 上传程序又称为下载程序h…

html+css+js网页设计 婚庆网站8个页面

htmlcssjs网页设计 婚庆网站8个页面 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#xff…

C#骑砍逻辑类Mod制作详细解说

前言&#xff1a; 最近在研究骑砍的mod&#xff0c;主要是想修改其中的逻辑部分&#xff0c;因此有了这篇帖子。 一&#xff0c;文件夹与XML配置 在Modules创建一个新文件夹&#xff0c;文件夹名称随意&#xff0c;不影响实际的读取。 文件夹下面的位置需要固定&#xff0c;因…

闲置物品|基于SprinBoot+vue的校园闲置物品交易平台(源码+数据库+文档)

校园闲置物品交易平台 目录 基于SprinBootvue的校园闲置物品交易平台 一、前言 二、系统设计 三、系统功能设计 5.1系统功能实现 5.2管理员模块实现 5.3用户模块实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xf…

项目:基于TCP的文件传输系统

项目介绍: 模拟FTP原理&#xff1a;客户端连接服务器后&#xff0c;向服务器发送一个文件。文件名可以通过参数指定&#xff0c;服务器端接收客户端传来的文件&#xff08;文件名随意&#xff09;&#xff0c;如果文件不存在自动创建文件&#xff0c;如果文件存在&#xff0c;…

matlab 相位解缠

目录 一、功能概述1、相位解缠2、主要函数二、代码实现1、螺旋线的正确相位角2、使用不同阈值平移相位角3、将相移应用于矩阵三、参考链接本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的抄袭狗。 一、功能概述 1、相位解缠 对…

FPGA实现多功能SDI视频采集卡,基于GTX+RIFFA架构,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案本博已有的 SDI 编解码方案 3、详细设计方案设计框图SDI 输入设备Gv8601a 均衡器GTX 解串与串化SMPTE SD/HD/3G SDI IP核BT1120转RGBFDMA图像缓存RIFFA用户数据控制RIFFA架构详解Xilinx 7 Series Integrated Bloc…

智能优化特征选择|基于鲸鱼WOA优化算法实现的特征选择研究Matlab程序(XGBoost分类器)

智能优化特征选择|基于鲸鱼WOA优化算法实现的特征选择研究Matlab程序&#xff08;XGBoost分类器&#xff09; 文章目录 一、基本原理鲸鱼智能优化特征选择流程 二、实验结果三、核心代码四、代码获取五、总结 智能优化特征选择|基于鲸鱼WOA优化算法实现的特征选择研究Matlab程序…

从地图信息实时检测路口的各向通行状况、红绿灯及溢出情况

高德地图、百度地图都能获得实时的道路信息。 C# 编写的路况信息爬虫可获得准实时&#xff08;1分钟间隔&#xff09;的路口的各向通行状况、红绿灯及溢出情况。 优势&#xff1a; 投入少&#xff0c;效果好&#xff0c;无需安装设备&#xff1b; 缺陷&#xff1a; 时间间隔…

更新RK3588开发板的rknn_server和librknnrt.so【这篇文章是RKNPU2从入门到实践 --- 【5】的配套文章】

作者使用的平台有&#xff1a; 一台装有Windows系统的宿主机&#xff0c;在该宿主机上装有Ubuntu 20.04虚拟系统&#xff1b; 瑞芯微RK3588开发板&#xff0c;开发板上的系统为Ubuntu22.04系统&#xff1b; 更新板子的 rknn_server 和 librknnrt.so&#xff0c;rknn_server 和…

USART之串口发送+接收应用案例

文章目录 前言一、电路接线图二、应用案例代码三、应用案例分析3.1 USART模块初始化3.1.1 RCC开启时钟3.1.2 GPIO初始化3.1.3 配置USART3.1.4 开启中断、配置NVIC3.1.5 开启USART 3.2 USART串口收发模块3.2.1 Serial_SendByte&#xff08;发送一个字节数据&#xff09;3.2.2 US…

【蓝桥杯集训100题】scratch绘制扇子 蓝桥杯scratch比赛专项预测编程题 集训模拟练习题第28题

scratch绘制扇子 蓝桥杯集训100题第28题模拟练习解析 此题曾经作为第十届省赛的真题考过 一、题目要求 以坐标(0,0)点为中心绘制一把扇子;扇面和扇把都是三分之一圆,扇面的半径 为 100 左右,扇把的半径为 20 左右。 编程实现 每次点击绿旗后,舞台背景为白色,…