代码随想录算法训练营DAY32|C++贪心算法Part.2|122.买卖股票的最佳时机II、55.跳跃游戏、45.跳跃游戏II

文章目录

  • 122.买卖股票的最佳时机II
    • 思路
    • CPP代码
  • 55.跳跃游戏
    • 思路
    • CPP代码
  • 45.跳跃游戏II
    • 思路
      • 方法一
      • 代码改善
    • CPP代码

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

力扣题目链接

文章讲解:122.买卖股票的最佳时机II

视频讲解:

状态:本题可以用动态规划,但是贪心也是能做出来的

本题中首先要明确两个:

  • 只有一只股票;
  • 当前只有买股票或者卖股票的操作

想要获得利润至少要两天为一个交易单元

思路

本题最难受的就是低点和高点不太好找, 但是,如果我们从贪心的角度来思考一个局部问题。

如果我们根据当前的股票价格数组,把利润分解为每天为单位的维度。这样我们就可以得到每天的利润序列:

在这里插入图片描述

现在我们可以得出我们的

局部最优:收集每天的正利润

result += max(prices[i] - prices[i - 1], 0);

全局最优:求得最大利润

CPP代码

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;
    }
};

55.跳跃游戏

力扣题目链接

文章链接:55.跳跃游戏

视频链接:贪心算法,怎么跳跃不重要,关键在覆盖范围 | LeetCode:55.跳跃游戏

状态:感觉贪心算法的题都好有意思,但是这题挺难想,局部整成啥呢?

思路

脑经急转弯:只要每次得到最大的可跳范围就行。根本就不需要我们是跳一步两步还是三步。

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

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

贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围)

整体最优解:最后得到整体最大覆盖范围,看是否能到终点

从上文可以看出,我们要比较当前范围下能扩充的最终范围。

CPP代码

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;
    }
};

45.跳跃游戏II

力扣题目链接

文章链接:45.跳跃游戏II

视频链接:贪心算法,最少跳几步还得看覆盖范围 | LeetCode: 45.跳跃游戏 II

状态:

思路

在[55.跳跃游戏](# 55.跳跃游戏)中,重点在于能够跳到终点;

在本题中,重点在于最少多少步跳到终点。

但是一个基本思路还是类似的,就是关于覆盖范围的概念。我们每一步都应该是尽可能得去增加我们的覆盖范围。

所以本题可以这样理解:我们用最少的步数去增加我们的覆盖范围

本题的贪心思路如下:

局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加1

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

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

方法一

首先要明确的如果数组长度只有1,那么直接返回0;

if (nums.size() == 1) return 0;

其次,明确当前覆盖最远范围的下标和下一步覆盖最远范围的下标;

int curDistance = 0, ans = 0, nexDistance = 0;

我们开始遍历数组,并且要开始收集下一步能跳多远,并且更新步数。

for (i = 0; i < nums.zie(); i++){
  //nextDistance =  i + nums[i]; 下一步能跳多远,但是我们应该记录下一步里跳得最远的
  nexDistance = max(nexDistance, i + nums[i]);
  if (i == curDistance){//遇到当前覆盖最远距离的下标
    ans++; //走一步
    curDistance = nextDistance//更新当前最远距离下标
    if (nextDistance >= nums.size() - 1) break;
  } 
}
return ans;

最关键的就是搞清楚什么时候步数+1。

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

个人觉得思路很结点,带式代码还是很绕的。

代码改善

这里也是一种思路的改善,就是我们不再关注当前覆盖最远距离的下标是不是终点。

让移动下标指向nums.size - 2

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

CPP代码

//方法一
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;
    }
};
//方法二
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;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux进程地址空间及其页表

文章目录 一、引言二、Linux进程地址空间的概念1、进程地址空间定义2、进程地址空间的组成3、进程地址空间与物理内存的关系 三、页表与内存映射1、页表的定义及作用2、页表的缺页中断 三、进程的写时拷贝 一、引言 在Linux中&#xff0c;进程管理是其核心功能之一&#xff0c…

OpenCV如何实现拉普拉斯算子的离散模拟

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV的Sobel 衍生品 下一篇 &#xff1a;OpenCV 如何实现边缘检测器 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 Laplacian&#xff08;&#xff09; 实…

Docker基本管理和虚拟化

一、docker的发展历史 https://www.cnblogs.com/rongba/articles/14782624.htmlhttps://www.cnblogs.com/rongba/articles/14782624.html 二、docker的概述 Docker是一个开源的应用容器引擎&#xff0c;基于go语言开发并遵循了apache2.0协议开源。 Docker是在Linux容器里运行…

Amazon云计算AWS之[2]弹性计算云EC2

文章目录 说明EC2基本架构Amazon机器映象&#xff08;AMI&#xff09;实例&#xff08;Instance&#xff09;弹性块存储&#xff08;EBS&#xff09; EC2关键技术地理区域和可用区域EC2通信机制弹性负载均衡监控服务自动缩放服务管理控制台 EC2安全及容错机制EC2弹性IP地址 说明…

开曼群岛:Web3企业的乐园

开曼群岛&#xff1a;Web3企业的理想之地 开曼群岛&#xff0c;在数字革命中大放异彩。近年来&#xff0c;该地区成立的Web3企业数量显著增加&#xff0c;如果保持目前的发展速度&#xff0c;并持续优化立法&#xff0c;那么扩展的速度将无可限量。本文将探讨推动这一增长的关…

使用Pycharm运行spark实例时没有pyspark包(ModuleNotFoundError: No module named ‘py4j‘)

一、问题描述 在安装并配置pyspark&#xff0c;下载并打开Pycharm&#xff08;专业版&#xff09;后进行spark实例操作&#xff08;笔者以统计文件中的行数为例&#xff09;时&#xff0c;运行程序后提示ModuleNotFoundError: No module named py4j&#xff1a; 二、解决办法 …

小程序线多点路图绘制

需求 当接口返回一连串地图坐标&#xff0c;需要根据这些坐标串联起来&#xff0c;形成一个线路图&#xff08;本次使用步行导航线路图&#xff09;。 思路 首先优先想到使用小程序Map组件的polyline属性去进行展示。但是我们发现直接使用该属性进行坐标绘制画出来的数据都是…

恶补《操作系统》2_1——王道学习笔记

2操作系统-进程 2.1_1 进程的定义、组成、组织方式、特征 组成&#xff1a;PCB&#xff08;进程存在唯一的标志&#xff09;&#xff0c;程序段&#xff0c;数据段 组织方式&#xff1a;链接方式&#xff0c;指针指向不同的队列&#xff1b;索引方式&#xff0c;索引表 特征…

fnm:Rust开发的高效Node版本管理工具

简介 fnm 是一个基于 Rust 开发的 Node 版本管理工具&#xff0c;它的目标是提供一个快速、简单且可靠的方式来管理 Node.js 的不同版本。同时&#xff0c;它是跨平台的&#xff0c;支持 macOS、Linux、Windows。&#x1f680; Fast and simple Node.js version manager, buil…

ISP比普通的静态代理相比有什么优势?

ISP&#xff08;Internet Service Provider&#xff09;&#xff0c;即互联网服务提供商&#xff0c;是向广大用户综合提供互联网接入业务、信息业务、增值业务的电信运营商。而静态代理则是一个固定不变的代理IP地址&#xff0c;具有稳定性强、兼容性好和管理方便等特点。当我…

QT中基于TCP的网络通信

QT中基于TCP的网络通信 QTcpServer公共成员函数信号 QTcpSocket公共成员函数信号 通信流程服务器端通信流程代码 客户端通信流程代码 使用Qt提供的类进行基于TCP的套接字通信需要用到两个类&#xff1a; QTcpServer&#xff1a;服务器类&#xff0c;用于监听客户端连接以及和客…

再谈C语言——理解指针(二)

指针变量类型的意义 指针变量的⼤⼩和类型⽆关&#xff0c;只要是指针变量&#xff0c;在同⼀个平台下&#xff0c;⼤⼩都是⼀样的&#xff0c;为什么还要有各种各样的指针类型呢&#xff1f; 其实指针类型是有特殊意义的&#xff0c;我们接下来继续学习。 指针的解引⽤ 对⽐…

Linux下的UDEV机制/守护进程

一. Udev机制概念引入 ( 需要在 etc/udev/rules.d/ 下创建设备的相关规则&#xff0c;不然有可能udev机制生成的设备文件不具备可读可写的权限&#xff0c;adb无法成功通过该设备文件访问设备 ) a. 创建文件夹 sudo vim Xiaomi-audroid.rules b. 添加规则 …

Laravel 6 - 第十四章 响应

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

(ICML-2021)从自然语言监督中学习可迁移的视觉模型

从自然语言监督中学习可迁移的视觉模型 Title&#xff1a;Learning Transferable Visual Models From Natural Language Supervision paper是OpenAI发表在ICML 21的工作 paper链接 Abstract SOTA计算机视觉系统经过训练可以预测一组固定的预定目标类别。这种受限的监督形式限制…

LabVIEW与Modbus协议的多点温度监控系统

LabVIEW与Modbus协议的多点温度监控系统 随着工业自动化和智能化水平的不断提升&#xff0c;对于现场监控技术的需求日益增长。开发了一种基于LabVIEW与Modbus协议的多点温度监控系统&#xff0c;实现高效、准确的温度数据采集、处理和显示&#xff0c;以及数据存储功能&#…

c++设计模式之桥接模式(拼接组合)

桥接模式&#xff1a;就是进行拼接组装 应用举例&#xff1a; 1.定义了形状&#xff0c;抽象形状接口&#xff0c;圆&#xff0c;矩形 2.定义了颜色&#xff0c;抽象颜色接口&#xff0c;红色&#xff0c;蓝色 3&#xff0c;怎么桥接&#xff0c;抽象具体形状和具体颜色的组合…

酷开科技逐步为用户构建健全的智慧家庭生活场景

大规模与精细化人群技术则是通过大量的计算能力和精细化的运营能力&#xff0c;建立用户专属数据储存区域&#xff0c;使得用户在使用不同电视的观影偏好和兴趣能够能够得以延续。 不拘泥于自有品牌终端数量&#xff0c;酷开系统除了集成在创维电视上&#xff0c;还服务于飞利…

大模型的实践应用22-谷歌Gemma AI大模型的架构原理,以及Gemma模型的部署安装本地教程

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用22-谷歌Gemma AI大模型的架构原理,以及Gemma模型的部署安装本地教程。谷歌Gemma AI大模型是由Google AI团队开发并开源。Gemma模型采用Transformer编码器-解码器架构,并加入了一些改进,例如使用稀疏注意力机制来提高推…

【计算机网络】MAC地址简介

MAC&#xff08;Medium Access Control&#xff09;&#xff0c;即媒介访问控制&#xff0c;是计算机网络通信中的重要概念。每个NIC&#xff08;Network Interface Card&#xff09;&#xff0c;即网络适配器&#xff0c;都具有独自且不变的MAC地址&#xff08;烧录的&#xf…
最新文章