【贪心算法】C++ 解决算法题:买卖股票 / K次取反 / 按身高排序 / 优势洗牌

1. 前言

1.1 贪心算法介绍

贪心算法(Greedy Algorithm)是一种在每一步选择中都采取当前状态下最优决策的算法。贪心算法通常用来解决最优化问题,其核心思想是通过局部最优解逐步推导出全局最优解。

在贪心算法中,我们并不总是考虑到未来可能发生的情况,而是只关注当前的最优选择。这种贪心选择性质使得贪心算法特别适合解决那些具有最优子结构性质的问题,即局部最优解能够推导出全局最优解的问题。

贪心算法的基本思路可以总结为以下几步:

  1. 确定问题的最优子结构:问题的最优解可以通过子问题的最优解逐步推导得到。
  2. 构造贪心选择:在每一步都做出当前状态下的最优选择,即局部最优解。
  3. 证明贪心选择性质:证明每一步的贪心选择都是最优的,能够推导出全局最优解。

需要注意的是,贪心算法并不适用于所有的问题,因为并非所有问题都具有最优子结构性质。在某些情况下,贪心算法得到的结果可能并不是全局最优解,而只是一个较好的解。因此,在应用贪心算法时,需要仔细分析问题的特性,以确定贪心算法是否适用于该问题。

下面会介绍一些用贪心解决的算法题:

2. 算法题

2.1_买卖股票的最佳时机

在这里插入图片描述
分析:

  • 买卖股票类的问题首先有一个通用解法,就是动态规划(之前有写),这里用贪心解:
  • 题目要求最多只能进行一次交易,因此我们可以利用循环解题

思路:

  • 创建两个变量ret负责记录统计过的当前最大利润,以及一个minPrev用于记录最小的买入价格
  • 通过遍历数组,每次对两变量进行更新,最后的ret就是结果

代码:

class Solution {
public:int maxProfit(vector<int>& prices) {int ret = 0;for(int i = 0, minPrev = INT_MAX; i < prices.size(); ++i){ret = max(ret, prices[i] - minPrev); // 更新结果minPrev = min(minPrev, prices[i]);}return ret;}
};

2.2_买卖股票的最佳时机II

在这里插入图片描述

分析:

  • 本题与上一题的区别在于:上一题只有一次交易机会本题可以多次交易,但是不能同时进行多笔交易,必须保证当前未持股时才能买入。

思路:
在这里插入图片描述

  • 我们只要保证每次做到低进高出即可,即在递增起点买入,终点卖出;
    此时有两种解决方法:
    • ① 以天数为指标:遍历数组,只要出现递增,那么就将这段递增的值加入到结果ret中
    • ② 利用双指针:本质是一样的,int i遍历数组,当找到一处递增时,用指针j将该递增区间统计,当走出递增时,将i和j间的距离就是这一段的递增值(利润)

代码:

  • 利用天数:
class Solution {
public:int maxProfit(vector<int>& prices) {// 利用天计算int ret = 0, n = prices.size();for(int i = 1; i < n; ++i){if(prices[i] > prices[i-1])ret += prices[i] - prices[i-1];}return ret;}
};
  • 利用双指针:
class Solution {
public:int maxProfit(vector<int>& prices) {// 利用双指针int ret = 0, n = prices.size();for(int i = 0; i < n; ++i){int j = i;while(j + 1 < n && prices[j+1] > prices[j])j++;ret += prices[j] - prices[i];i = j; // 更新i到j+1}return ret;}
};

2.3_K次取反后最大化的数组和

在这里插入图片描述

分析:

  • 题目要求找到对整数数组nums的元素进行k次取反操作后的最大和,自然要先对负数取反,其次再对罪小的正数进行取反(贪心)

思路:

  • 首先统计负数的个数,先将可以反转的负从最小的进行开始反转,如果所有负数均反转,且仍k>0
  • 此时从小到大反转正数
  • (这个过程也可以通过一个priority_queue来完成)

代码:

class Solution {
public:int largestSumAfterKNegations(vector<int>& nums, int k) {int n = nums.size(), minElem = INT_MAX;int m = 0;for(auto x : nums) // 统计负数个数m{if(x < 0) ++m;minElem = min(minElem, abs(x)); // 找数组中绝对值最小的数}int ret = 0;if(m > k){sort(nums.begin(), nums.end());// 将前k小的负数转正,并统计到retfor(int i = 0; i < k; ++i)ret += abs(nums[i]);for(int i = k; i < n; ++i)ret += nums[i];}else // m == k: 将所有负数转正{// m < k:// 先将所有负数转正;后根据k-m的奇偶性进行编写for(auto x : nums)ret += abs(x);if((k - m) % 2) // 奇数 // 将当前数组的绝对值最小逆号ret -= minElem * 2;}return ret;}
};

2.4_按身高排序

在这里插入图片描述

分析:

  • 本质就是根据数组2的数据对数组1进行排序,可以利用vector 以及 pair<type, type> 二元组来完成;也可以创建一个下标数组,根据身高对下标数组进行排序,最后直接输出names[index[i]]

思路:

  • ① 创建一个vector<pair<int, string>> people,再将身高信息和姓名信息存放到该people进行降序排序
  • ② 创建并初始化一个下标映射的数组index,排序index(利用lambda表达式)根据身高信息逆序排序,最后返回姓名names[index[i]]

代码:

  • 利用二元组:
class Solution {
public:vector<string> sortPeople(vector<string>& names, vector<int>& heights) {// 利用二元组int n = names.size();vector<pair<int, string>> people;for (int i = 0; i < n; ++i) {people.push_back(make_pair(heights[i], names[i]));}// 根据身高降序sort(people.rbegin(), people.rend());// 提取结果vector<string> ret;for (const auto& p : people) {ret.push_back(p.second);}return ret;}
};
  • 利用下标数组:
class Solution {
public:vector<string> sortPeople(vector<string>& names, vector<int>& heights) {// 根据身高对下标进行排序: // 创建下标数组int n = heights.size();vector<int> index(n);for(int i = 0; i < n; ++i)index[i] = i;// 排序数组sort(index.begin(), index.end(), [&](const int i, const int j){return heights[i] > heights[j];});vector<string> ret;// 提取结果到数组for(int i = 0; i < n; ++i){ret.push_back(names[index[i]]);}return ret;}
};

2.5_优势洗牌

在这里插入图片描述

分析:

  • 要使优势最大,则应该尽量使用较小的大值(在nums1中找大于nums2[i]的最小值),类似田忌赛马的排列规则

思路:

  1. 首先对nums1进行排序(便于找大于nums2[i]的最小值),由于要根据nums2更改nums1,所以不能排序nums2,创建一个下标数组并根据nums2进行排序,就可以利用index按大小顺序访问nums2的元素
  2. 创建ret,用于存放nums1改变后的位置
  3. 遍历nums1,此时的思路就是田忌赛马的思路,对于当前元素(nums1未匹配的最小元素):
    • 如果大于nums2[index2[left]](当前最小元素),就直接匹配该元素
    • 如果小于nums2[index2[left]],那就匹配nums2的最大的元素

代码:

class Solution {
public:vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {// 1. 排序数组int n = nums1.size();sort(nums1.begin(), nums1.end());// 1.5 创建下标数组vector<int> index2(n);for(int i = 0; i < n; ++i)index2[i] = i;sort(index2.begin(), index2.end(), [&](const int i, const int j){return nums2[i] < nums2[j]; });// 2. 田忌赛马: 如果当前比得过,则插入当前位置// 如果比不过,则匹配对方最大的int left = 0, right = n-1;vector<int> ret(n);for(auto x : nums1){if(x > nums2[index2[left]]) ret[index2[left++]] = x;else ret[index2[right--]] = x;}return ret;}
};

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

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

相关文章

云计算-交互式数据处理 (Interactive Data Processing)

AWS Glue DataBrew (AWS Glue DataBrew) 数据预处理是任何数据分析任务之前的重要步骤。AWS Glue DataBrew 是一个可视化工具&#xff0c;允许我们预处理数据&#xff0c;包括清洗和规范化数据。此AWS服务提供许多数据准备功能&#xff0c;包括分组、联接、过滤、重新采样、排序…

【数据结构(邓俊辉)学习笔记】二叉树04——Huffman树

文章目录 0. 概述1. 无前缀冲突编码2. 编码成本3. 带权编码成本4. 编码算法5. 算法实现流程6. 时间复杂度与改进方案 0. 概述 学习Huffman树。 1. 无前缀冲突编码 在加载到信道上之前&#xff0c;信息被转换为二进制形式的过程称作编码&#xff08;encoding&#xff09;&…

【随笔】Git 实战篇 -- Git Rebase出错?手把手教你如何优雅地解决常见问题 (四十二)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

JAVA系列:NIO

NIO学习 一、前言 先来看一下NIO的工作流程图&#xff1a; NIO三大核心组件&#xff0c;channel&#xff08;通道&#xff09;、Buffer&#xff08;缓冲区&#xff09;、selector&#xff08;选择器&#xff09;。NIO利用的是多路复用模型&#xff0c;一个线程处理多个IO的读…

探秘三相交流电子负载应用

三相交流电子负载是模拟实际负载的电子设备&#xff0c;主要用于电源、电机、变压器等产品的性能测试和老化试验。它能够精确控制电流、电压、频率等参数&#xff0c;模拟各种复杂的负载情况&#xff0c;为产品研发和质量控制提供可靠的测试手段。 三相交流电子负载在电源产品测…

4. 排序算法

文章目录 1.简单排序1.1 冒泡排序1.1.1 步骤核心思想1.1.2 参考代码1.1.3 时间复杂度1.1.4 空间复杂度1.1.5 优化 1. 2. 选择排序1.2.1 核心思想1.2.2 步骤1.2.3 参考代码1.2.4 时间复杂度1.2.5 空间复杂度1.2.6 优化 1.3 插入排序1.3.1 思想1.3.2 步骤1.3.3 参考代码1.3.4 时间…

js使用链表实现音乐播放器(新增,下一首播放,置顶,删除)

什么是链表 链表是一种线性数据结构&#xff0c;与数组类似&#xff0c;它用于存储一系列元素。不过&#xff0c;与数组在内存中连续存储元素不同&#xff0c;链表中的元素&#xff08;称为节点&#xff09;在内存中可以是非连续存放的。每个节点包含两部分&#xff1a;一部分…

Java开发的saas模式智能制造超强云MES系统源码springboot+mysql+uniapp一整套云MES系统源码

Java开发的saas模式智能制造超强云MES系统源码springbootmysqluniapp一整套云MES系统源码 智能制造超强云MES系统概述&#xff1a; MES以生产车间管理为核心&#xff0c;帮助企业实现生产动态监控和管理。把制造数据管理、计划排程管理、生产调度管理、库存管理、质量管理、人…

swagger-ui页面接口的入参出参与代码实体类不一致有差异、swagger请求实体与预期定义不符、swagger参数与实体中参数不一致原因分析

文章目录 一、问题背景二、问题原因及解决方法 一、问题背景 项目集成swagger之后&#xff0c;发现有个接口的请求跟接口对应不上&#xff0c;把其他接口的请求参数放到当前这个请求上了。 如下图&#xff1a;test1接口的请求参数是其他请求的&#xff0c;并不是test1接口的 …

win10如何查看本机ip地址?三招搞定,快来试试吧

在数字化时代&#xff0c;IP地址作为网络设备的唯一标识&#xff0c;对于计算机使用者来说具有重要意义。无论是为了进行网络设置、远程连接&#xff0c;还是解决网络问题&#xff0c;了解如何查看本机IP地址都是一项必备技能。对于使用Windows 10操作系统的用户来说&#xff0…

简单的 Cython 示例

1&#xff0c; pyx文件 fibonacci.pyx def fibonacci_old(n):if n < 0:return 0elif n 1:return 1else:return fibonacci_old(n-1) fibonacci_old(n-2) 2&#xff0c;setup.py setup.py from setuptools import setup from Cython.Build import cythonizesetup(ext_mod…

node.js(express)+MongoDB快速搭建后端---新手教程

前言&#xff1a; Node.js是一个基于 Chrome V8引擎的JavaScript运行环境&#xff0c;是对于前端工程师来说学习成本最小的后端实现方法&#xff0c;本篇文章总结如何从0-1写一个后端的登录接口 一、检查node环境 先检查自己的node是否安装 一般来说前端工程师的电脑环境肯定…

六面体大米装袋机在提升大米包装效率中的作用

在当今社会&#xff0c;随着科技的飞速发展&#xff0c;各行各业都在寻求创新与突破&#xff0c;以提升生产效率和降低成本。而在大米包装领域&#xff0c;六面体大米装袋机的出现&#xff0c;无疑为整个行业带来了革命性的变化。这种先进的机械设备不仅提高了大米的包装效率&a…

【全开源】沃德校友会管理系统(FastAdmin+ThinkPHP+Uniapp)

一款基于FastAdminThinkPHPUniapp开发的校友会综合服务平台&#xff0c;即校友信息管理平台、活动管理平台、校友服务大厅、校友企业服务平台等&#xff0c;实现集中学校、学院、校友会于一体的基础服务平台的搭建&#xff0c;建设一个满足校友信息化长期发展的、可扩展的综合校…

全面盘点多模态融合算法及应用场景

关注作者&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕博&#xff0c;复旦机器人智能实验室成员&#xff0c;阿里云认证的资深架构师&#xff0c;项目管理专业人士&#xff0c;上亿营收AI产品研发负责人 多…

一款更加轻量级的虚拟机:Multipass

一款更加轻量级的虚拟机&#xff1a;Multipass 前言Multipass概述安装Multipassmultipass命令命令使用说明 Multipass的使用查看镜像列表新建和运行虚拟机查看虚拟机列表查看虚拟机信息进入虚拟机外部操作虚拟机删除和释放实例初始化配置虚拟机的调整设置桥接网络接口配置软件源…

Oracle dblink 发现Network 等待事件的分析 enq: KO - fast object checkpoint

所有的sql 通过dblink 查询全部等待中&#xff0c; 同一个SQL 20多个session 在跑&#xff0c;等待事件network&#xff0c;可能怀疑是不是网络断开了&#xff0c;导致没有返回 执行sql 如下&#xff1a; BEGIN Xdblink ; END; 去到dblink 所在的db&#xff0c;发现20多个sql在…

白酒:白酒产地的地域文化与品牌形象

云仓酒庄豪迈白酒&#xff0c;作为中国白酒的一部分&#xff0c;其品牌形象深受产地的地域文化影响。地域文化是一个地区与众不同的文化传统和价值观&#xff0c;它影响着当地人的生活方式和审美观念&#xff0c;进而影响白酒的品牌形象。 首先&#xff0c;白酒产地的历史与传统…

ClickHouse安装教程:开启你的列式数据库之旅

ClickHouse是一个高性能的列式数据库管理系统&#xff0c;适用于在线分析处理&#xff08;OLAP&#xff09;。以下是ClickHouse的一些基本使用步骤&#xff1a; 下载二进制文件&#xff1a;您可以通过运行以下curl命令在Linux、FreeBSD或macOS上本地下载ClickHouse&#xff1a…

Midjourney如何控制光照?提示词灵感来了!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Midjourney如何控制光照&#xff1f;提示词灵感来了&#xff01;文章目录 前言总结 前言 Midjourney v6 已经更新好久了&#xff0c;你知道有哪些可以控制光照效果的关键词吗…