【贪心算法指针】C++ 解决子数组 / 子序列的相关问题(最大数、数组和减半的最小操作数、连续/递增序列)

文章目录

  • 1. 前言
    • 1.1 贪心算法介绍
  • 2. 算法题
    • 2.1_将数组和减半的最少操作次数
    • 2.2_最大数
    • 2.3_最长递增子序列
    • 2.4_递增的三元子序列
    • 2.5_最长连续递增序列
    • 2.6_数组中的最长连续子序列
    • 2.7_在字符串中找出连续最长的数字串

1. 前言

1.1 贪心算法介绍

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

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

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

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

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

下面我们会解决一些 数组相关的算法题(子数组、子序列类问题)


2. 算法题

2.1_将数组和减半的最少操作次数

在这里插入图片描述

  • 题意分析:题目要求将数组nums的数组和至少减少一半的最少操作数
  • 思路分析:要求使数组和减少一半的最少操作,自然我们可以每次对最大的数进行减半操作(贪心),如何进行?—— 利用堆
    • 此时就有了思路:将数组元素加入到堆heap中,统计数组和的一半sum后,通过一个循环每次提取堆顶元素进行减半,直到sum<=0

代码:

class Solution {
public:int halveArray(vector<int>& nums) {priority_queue<double> heap;// 统计sumdouble sum = 0.0;for(auto x : nums){heap.push(x);sum += x; }sum /= 2.0;// 统计最少操作次数int count = 0;while(sum > 0){double tmp = heap.top() / 2;heap.pop();sum -= tmp;++count;heap.push(tmp);}return count;}
};

2.2_最大数

在这里插入图片描述

  • 题意分析:题目要求将给定的一组整数重排使其最大
  • 思路分析:要得到最大的重排结果,自然会想到将更大的数放到前面(贪心),这里如何排列顺序就是重点
    • 思路:
      • 将所给的数转为字符串,便于设定规则比较
      • 由于字符串是根据字典序比较的,“23” > “221”,排到前面,是和我们想要的规则一致的,则直接对字符串数组进行排序(根据两个元素的先后顺序大小)
      • 最后提取结果即可(注意全0的情况)

代码:

class Solution {
public:string largestNumber(vector<int>& nums) {// 将数字转换为字符串vector<string> strs;for(auto x : nums) strs.push_back(to_string(x));// 根据字符串排序// s1s2 > s2s1 则 s1s2在前,s2s1在后sort(strs.begin(), strs.end(), [&](const string& s1, const string& s2){return s1 + s2 > s2 + s1;});// 提取结果string ret;for(auto s : strs)ret += s;// 判断特殊情况:000000...->0if(ret[0] == '0') return "0";return ret;}
};

2.3_最长递增子序列

在这里插入图片描述

  • 题意分析:题目要找到数组的最长递增子序列的长度
  • 思路分析:首先对于这道题,是可以利用动态规划解题的;而对于贪心,我们可以用一个数组存放长度为n时的最后一位元素是什么,具体规则在下图:
    • 思路:
      在这里插入图片描述
    • 找ret中大于nums[i]的最小值的过程可以用二分查找进行优化

代码:

class Solution {
public:int lengthOfLIS(vector<int>& nums) {// 贪心vector<int> ret;ret.push_back(nums[0]);for(int i = 0; i < nums.size(); ++i){if(nums[i] > ret.back()) {ret.push_back(nums[i]);} else { // 二分查找int left = 0, right = ret.size() - 1;while(left < right){int mid = (left + right) >> 1;if(ret[mid] < nums[i])left = mid + 1;elseright = mid;}ret[left] = nums[i]; // 插入}}return ret.size();}
};

2.4_递增的三元子序列

在这里插入图片描述

  • 题意分析:题目要求找是否存在长度为3的递增子序列,实际上算是前面递增子序列的变体。
  • 思路分析:同理于上一题,首先可以使用动态规划解决,每次计算判断是否dp[i]为3即可,对于贪心,我们依然采取一样的策略,但可以进行优化
    • 思路:
    • 用变量a表示长度为1时的元素,变量b表示长度为2 的最后一位元素,遍历数组,只要存在一个nums[i] > b,就证明有长度为3的递增子序列

代码:

class Solution {
public:bool increasingTriplet(vector<int>& nums) {int a = nums[0], b = INT_MAX;for(auto x : nums){if(x > b) return true;else if (x > a) b = x;else a = x;}return false;}
};

2.5_最长连续递增序列

在这里插入图片描述

  • 题意分析:读题后发现,该题实际上就是找最长的递增子数组(子数组和子序列的区别就在于是否连续)
  • 思路分析:对于连续子数组,可以直接利用双指针进行解题:
    • 思路:
    • 创建两指针left、right
    • 遍历数组,如果出现递增则right++,否则就更新结果并将left移动到right位置,继续寻找;

代码:

class Solution {
public:int findLengthOfLCIS(vector<int>& nums) {vector<int> tmp(nums.begin(), nums.end());tmp.push_back(INT_MIN); // 用于简化特殊处理int ret = 0;int i = 0, j = 1; // 即left 于 rightwhile (i < tmp.size() && j < tmp.size()) {if (tmp[j - 1] < tmp[j]) {++j;} else {// 更新结果 + 移动 i 指针ret = max(ret, j - i);i = j; // 将 i 指针移到 j 的位置继续寻找连续递增子序列++j; // 同时移动 j 指针}}return ret;}
};

2.6_数组中的最长连续子序列

在这里插入图片描述

在这里插入图片描述

  • 题意分析:题目要求找到连续子序列,注意这里的连续要求的是值连续,位置不用连续(所以可以先进行排序、排序后本质就变成了子数组问题)
  • 思路分析:这道题可以使用哈希表;这里我们先排序、随后遍历数组,利用两个变量(curLen、maxLen)解题。
    • 思路:
    • 创建变量curLen(当前连续子序列的长度)、maxLen(连续子序列的最大长度)
    • 遍历数组,i指针用于遍历数组,当出现连续,则cur++,不连续就更新结果值max,并重置cur
    • (本质是和双指针一样的在这里插入图片描述

代码:

int MLS(vector<int>& arr) {sort(arr.begin(), arr.end());int curLen = 1, maxLen = 1;for (int i = 1; i < arr.size(); ++i){if (arr[i - 1] != arr[i]) // 不等于前一元素{if (arr[i - 1] + 1 == arr[i]) { // 连续curLen++;}else { // 不连续maxLen = max(maxLen, curLen);curLen = 1;}}}return max(curLen, maxLen);
}

2.7_在字符串中找出连续最长的数字串

在这里插入图片描述

  • 题意分析:题目要求找到字符串中的最长连续数字串,即最长的数字子数组
  • 思路分析:自然我们可以使用双指针来解题:
    • 思路:
    • i指针负责遍历数组,一直++,直到遇到数字串时,将j数组移动到i的位置用来遍历该数字串,走出数字串后更新结果
    • 需要注意的是该题会存在多个长度一样的数字串,所以需要用一个string数组来存储结果。

代码:

int findLongestNumSub() {string s;while (cin >> s) {int maxLen = 0; // 最长数字串的长度vector<string> substrings; // 存储最长数字串int i = 0, j = 0;while (i < s.size()) {while (i < s.size() && !(s[i] >= '0' && s[i] <= '9')) {++i;}j = i;while (j < s.size() && s[j] >= '0' && s[j] <= '9') {++j;}if (j - i > maxLen) {maxLen = j - i;substrings.clear();substrings.push_back(s.substr(i, maxLen));}else if (j - i == maxLen) {substrings.push_back(s.substr(i, maxLen));}i = j; // 移出数字串}for (const auto& sub : substrings) {cout << sub;}cout << "," << maxLen;cout << endl;} // end whilereturn 0;
}

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

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

相关文章

一文搞透常见的Python编码陷阱(上)(分析+案例)

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 一、别忘了冒号 1. if 语句 2. while 语句 3. for 语句 4. 函数定义 5. 类定义 6. try/except 语句 …

RTDETR结合CVPR2024最新图像增强算法!让你的模型无惧风雨【含端到端推理脚本】

如何有效地探索雨痕的多尺度表示对于图像去雨是很重要的。与现有的基于Transformer的方法相比,这些方法主要依赖于单一尺度的雨痕外观,我们开发了一个端到端的多尺度Transformer,利用各种尺度中潜在有用的特征来促进高质量的图像重建。为了更好地探索空间变化的雨痕的常见退…

满帮集团 Eureka 和 ZooKeeper 的上云实践

作者&#xff1a;胡安祥 满帮集团&#xff0c;作为“互联网物流”的平台型企业&#xff0c;一端承接托运人运货需求&#xff0c;另一端对接货车司机&#xff0c;提升货运物流效率。2021 年美股上市&#xff0c;成为数字货运平台上市第一股。根据公司年报&#xff0c;2021 年&a…

网络协议——FTP(简介、搭建FTP服务端)

一、简介 1、什么是FTP&#xff1f; FTP&#xff08;File Transfer Protocol&#xff0c;文件传输协议&#xff09; TCP/IP 协议组的协议之一。常用20&#xff08;数据&#xff09;、21&#xff08;命令&#xff09;端口作为通讯端口。&#xff08;22为SSH端口&#xff09;F…

就业班 第三阶段(ELK) 2401--5.22 day3 filebeat+elk云部署

kafka集群 Windterm同步输入&#xff0c;多台机子可以同时输入同步输入 启动kafka需要启动两个 第一个 [rootkafka1 ~]# cd /usr/local/kafka_2.11-2.0.0/ [rootkafka1 ~]# nohup bin/zookeeper-server-start.sh config/zookeeper.properties &第二个 [rootkafka1 ~]#…

20232810 肖峰 2023-2024-2 《网络攻防实践》实验十一

一、实践内容 &#xff08;1&#xff09;web浏览器渗透攻击 任务&#xff1a;使用攻击机和Windows靶机进行浏览器渗透攻击实验&#xff0c;体验网页木马构造及实施浏览器攻击的实际过程。 实验步骤&#xff1a; ①选择使用Metasploit中的MS06-014渗透攻击模块 ②选择PAYLOAD为任…

Linux 36.3@Jetson Orin Nano之系统安装

Linux 36.3Jetson Orin Nano之系统安装 1. 源由2. 命令行烧录Step 1&#xff1a;下载Linux 36.3安装程序Step 2&#xff1a;下载Linux 36.3根文件系统Step 3&#xff1a;解压Linux 36.3安装程序Step 4&#xff1a;解压Linux 36.3根文件系统Step 5&#xff1a;安装应用程序Step …

# Mybatis 高级用法和tk.mybatis使用

Mybatis 高级用法和tk.mybatis使用 文章目录 Mybatis 高级用法和tk.mybatis使用使用SelectProvider、InsertProvider、UpdateProvider、DeleteProviderSelectProvider使用例子 tk.mybatis引入依赖查询实现实体映射类实体类规范 dao层调用dao 使用SelectProvider、InsertProvide…

eBay运营账号防关联成功的关键因素是什么?

一、什么是ebay eBay如今的发展现状呈现出积极且充满活力的态势。作为全球知名的在线拍卖和购物平台&#xff0c;随着全球消费者对线上购物的需求不断增长&#xff0c;这为卖家提供了广阔的市场空间和盈利机会&#xff0c;但多账号的运营若处理不好容易引起账号被关联&#xf…

基于生命周期评价法的农田温室气体排放估算;农田CH4和N2O排放模拟;农田碳库模型和土壤呼吸等

目录 专题一 温室气体排放模拟研究 专题二 农田CH4和N2O排放模拟 专题三 农田碳库模型和土壤呼吸 专题四 基于生命周期评价法的农田温室气体排放估算 专题五-六 基于过程模型的温室气体排放模拟 专题七 案例模拟与疑难解答 更多应用 农业是甲烷&#xff08;CH4&#xff…

全球前五!ATFX 2024年Q1业绩狂飙,6240亿美元交易量彰显实力

5月&#xff0c;密集发布的报告显示&#xff0c;强者恒强是差价合约行业不变的竞争逻辑。而ATFX最新展现的业绩无疑是这一逻辑的有力例证。依照惯例&#xff0c;知名行业媒体Finance Magnates日前公布了全球经纪商最为关注的2024年第一季度行业报告。报告数据显示&#xff0c;A…

数据结构算法-堆(Heap)和优先队列

堆的概念 堆&#xff08;heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质&#xff1a; always greater than its child node/s and the key of the root node is the largest among all other nodes. This property…

第53期|GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

Python 全栈体系【四阶】(五十三)

第五章 深度学习 十二、光学字符识别&#xff08;OCR&#xff09; 2. 文字检测技术 2.3 DB&#xff08;2020&#xff09; DB全称是Differentiable Binarization&#xff08;可微分二值化&#xff09;&#xff0c;是近年提出的利用图像分割方法进行文字检测的模型。前文所提…

Git原理及常用命令小结——实用版(ing......)、Git设置用户名邮箱

Git基本认识 Git把数据看作是对小型文件系统的一组快照&#xff0c;每次提交更新&#xff0c;或在Git中保存项目状态时&#xff0c;Git主要对当时的全部文件制作一个快照并保存这个快照的索引。同时&#xff0c;为了提高效率&#xff0c;如果文件没有被修改&#xff0c;Git不再…

明日周刊-第11期

上周末去参加了软考&#xff0c;这个考试目前很热门&#xff0c;参加考试的人也非常多。笔者已经算是二战了&#xff0c;今年从笔试改革成了机考。618的购物活动也都已经开始了&#xff0c;我给狗子买了一袋进口的高端狗粮渴望&#xff0c;但是买回来发现它并不爱吃&#xff0c…

二叉树——堆的实现

一.前言 前面我们讲解了二叉树的概念以及二叉树的存储结构&#xff1a;https://blog.csdn.net/yiqingaa/article/details/139224974?spm1001.2014.3001.5502 今天我们主要讲讲二叉树的存储结构&#xff0c;以及堆的实现。 二.正文 1.二叉树的顺序结构及实现 1.1二叉树的顺序…

面向对象编程:坦克飞机大战游戏的重构之旅

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、面向对象编程思想入门 坦克对象的定义 属性与行为方法的实现 二、面向过程与面向对象…

关于RAG(检索增强生成)的一些知识

写在前面 最近一直在看AI相关的文章&#xff0c;不出意外的话&#xff0c;后续几篇应该都是关于这方面的。希望能和大家一起了解这方面的技术。 什么是RAG 检索增强生成 (RAG,全称Retrieval-Augmented Generation) 是一种利用从外部来源获取的事实来提高生成式 AI 模型的准确…

利用机器非学习进行后门攻击

信息安全是一个古老的计算机领域。许多 80 后还记得自己小时候经常听到的瑞星杀毒和江民杀毒软件。这些 90 年代火遍大江南北的信息安全工具&#xff0c;至今仍然影响着使用互联网和信息技术的千家万户。随着人工智能的兴起和普及&#xff0c;有越来越多的商业软件使用了人工智…