【贪心算法】C++解决回文串、增减字符串匹配、分发饼干、跳跃游戏、加油站问题

1. 前言

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

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

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

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

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

2. 算法题

2.1_最长回文串

在这里插入图片描述

题意分析

  • 题目要求找到字符串的 字符可以组成的最长回文串的长长度
  • 对于回文串,只要出现次数是偶数,就可以加上,最多只能出现一个单个字符(中间位)

思路

  • 由于只需要长度而不需要实际的串,我们可以利用哈希表和一个结果变量ret
  • hash统计各字符的出现次数:
    • ret直接加上所有字符的最高偶数次,最后如果s仍有元素,返回ret+1,否则ret就是最终结果

代码

class Solution {
public:int longestPalindrome(string s) {// 数组代替哈希int hash[127] = { 0 };for(char ch : s) hash[ch]++;// 统计结果int ret = 0;for(int x : hash)ret += x / 2 * 2; // 先加上所有偶数位(比如7个a,就加上6个)// 如果原始字符串的长度比计算出的偶数部分长度还要长,说明存在至少一个字符出现奇数次,因此需要额外再加上一个奇数长度。return ret < s.size() ? ret + 1 : ret;}
};

2.2_增减字符串匹配

在这里插入图片描述

题意分析

  • 根据题目,重点在于如何分配元素,使序列在满足当前比较关系的同时,不影响后面的分配

思路

  • 遍历字符串,当前字符为’I’插入最小的元素(保证当前元素一定小于后面)
  • 当前字符为’D’插入最大的元素(保证当前元素一定大于后面)
    代码
class Solution {
public:vector<int> diStringMatch(string s) {int left = 0, right = s.size();vector<int> ret;for(char ch : s){if(ch == 'I')ret.push_back(left++);elseret.push_back(right--);}ret.push_back(left); // 加上最后一位return ret;}
};

2.3_分发饼干

在这里插入图片描述
题意分析

  • 要求尽可能使更多的孩子满足,注意每个孩子只能吃一块饼干,有了这点我们就可以利用贪心,给每个孩子吃能满足自己的最小的饼干,如何做到?——排序

思路

  • 排序两数组,利用两指针:如果孩子的胃口小于饼干大小,就可以吃,记录结果,指针右移,反之找更大的饼干
  • 由于进行了排序,只要当前饼干不能满足当前孩子,自然更不能满足后面的孩子

代码

class Solution {
public:int findContentChildren(vector<int>& g, vector<int>& s) {// 排序数组sort(g.begin(), g.end());sort(s.begin(), s.end());int ret = 0, i = 0, j = 0; // 两数组的指针while(i < g.size() && j < s.size()){if(g[i] <= s[j])i++, j++, ret++;elsej++;}return ret;}
};

2.4_跳跃游戏 II

在这里插入图片描述

题意分析

  • 本题目像是 跳台阶 的变体:重点是 可以跳跃的距离根据当前数组元素的值决定
  • 题目要求找到最后一个位置的最小跳跃次数,即我们跳跃要尽可能的远。
  • 这里我们使用贪心,要尽可能的跳远:(当然这道题也可以使用动态规划解题)

思路

  • 我们可以利用两个指针,分别标记当前可以跳跃的左右区间范围
  • left <= right,进行循环:
    • 每次遍历left到right 找最大的跳跃距离max(maxPos, nums[i] + i)
    • 后根据maxPos更新下一次可以跳跃到的区间

代码

class Solution {
public:int jump(vector<int>& nums) {// 类似层序遍历int left = 0, right = 0, ret = 0, n = nums.size(), maxPos = 0;while(left <= right){// 跳到了最后if(maxPos >= n - 1) return ret;// 本次跳跃可以到的位置for(int i = left; i <= right; ++i)maxPos = max(maxPos, nums[i] + i); // 更新 maxPos 为当前位置能够到达的最远位置 left = right + 1, right = maxPos; // 下一次跳跃的范围ret++;}// 特殊情况,没到达最后return -1;}
};

顺便贴出动态规划解法(dp):

int jump(vector<int>& nums) {int n = nums.size();vector<int> dp(n, INT_MAX); // 初始化动态规划数组,初始值为无穷大dp[0] = 0; // 起始位置不需要跳跃for (int i = 1; i < n; ++i) {for (int j = 0; j < i; ++j) {if (j + nums[j] >= i) { // 如果位置 j 能够跳到位置 idp[i] = min(dp[i], dp[j] + 1); // 更新跳到位置 i 的最小跳跃次数}}}return dp[n - 1]; // 返回跳到最后一个位置的最小跳跃次数}

2.5_跳跃游戏

在这里插入图片描述
题意分析

  • 对于跳跃游戏Ⅰ, 只需要判断是否可以跳到最后一个下标:
  • 跟随上一题的思路使用贪心

思路

  • 跟随上一题的思路,当max >= n - 1时,返回true即可

代码

class Solution {
public:bool canJump(vector<int>& nums) {int left = 0, right = 0, maxPos = 0, n = nums.size();while(left <= right){// 跳到了最后一个位置if(maxPos >= n - 1) return true;for(int i = left; i <= right; ++i)maxPos = max(maxPos, nums[i] + i);left = right+1, right = maxPos;}// 到不了最后一个下标return false;}
};

2.6_加油站

在这里插入图片描述
题意分析

  • 题目要求从某个加油站出发,绕行一圈回到起点,使得途中不会因为油量不足而无法到达下一个加油站
  • 我们可以对这一过程进行模拟

思路

  • 遍历gas数组,对每一个起点进行枚举:
  • 从起点位置向后移动,每次计算剩余油量(利用循环),如果剩余<0,则该起点不合适,继续遍历
  • 直到出现走过一轮后,剩余油量依然>=0,此时返回下标

代码

class Solution {
public:int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int n = gas.size();for(int i = 0; i < n; ++i){int remain = 0, step = 0;for( ; step < n; ++step){int index = (i + step) % n; // index: 走step步后的下标remain += gas[index] - cost[index];if(remain < 0) break; // 无法到达下一站}if(remain >= 0) // 绕行了一圈return i;i += step; // 跳过已经遍历过的}return -1;}
};

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

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

相关文章

代理注册湖北武汉投资管理公司流程和条件

我公司代理注册湖北武汉投资管理公司&#xff0c;现在大家都知道全国的投资管理公司已经停批了&#xff0c;很多需要收购的老板都是通过收购现成的投资管理公司经营的&#xff0c;现在我告诉大家一个好消息&#xff0c;我们有渠道办理湖北武汉资产管理公司&#xff0c;详情致电…

521源码-免费源码下载-免费学习网站教程-宝塔面板ssl网站证书到期后弹出无法续期错误提示

宝塔面板如果从老版本升级到8.10后&#xff0c;当点站证书过期续期时会弹出错误&#xff1a; 排查文件是找不到问题出在哪里&#xff0c;导致续期错误。 解决办法&#xff1a;通过摸索&#xff0c;最简单的就是删除站点&#xff0c;注意&#xff1a;只是删除&#xff0c;不是把…

亚马逊VC账号产品热销,在美国哪些智能小家电产品最好卖?

亚马逊VC账号产品在美国市场的热销&#xff0c;反映了消费者对于特定智能小家电产品的强烈需求。智能小家电产品因其实用性、便捷性和科技感&#xff0c;近年来在美国市场备受追捧。 以下是一些在亚马逊VC账号上热销的智能小家电产品&#xff1a; 智能扫地机器人 这类产品在美…

[vue3后台管理一]vue3下载安装及环境配置教程

[vue3后台管理二]vue3下载安装element plus 一、vue3下载安装element plus cnpm install element plus二&#xff1a;修改main.js import { createApp } from "vue"; import App from "./App.vue"; import ElementPlus from "element-plus"; …

JAVA:Random详解

Java中的java.util.Random类用于生成伪随机数。它提供了多种方法来生成不同类型的随机数&#xff0c;包括整数、浮点数和布尔值。以下是对Random类及其主要方法的详细介绍 一、生成随机数 创建一个Random对象&#xff0c;可以使用以下两种方式&#xff1a; 无参构造函数&…

建议大家少用点儿网站测速工具

春节休息期间明月有接了几个服务器代运维的业务&#xff0c;期间就发现不少新手站长们还在用 17ce、站长工具等等这些网站测速工具来评判站点访问速度的&#xff0c;感觉很有必要给大家聊聊这个事儿&#xff0c;因为这毕竟也是一个涉及服务器安全的一个重要环节了。 其实&#…

那些不起眼但很好玩的API合辑

那些不起眼但很好玩的API&#xff0c;为我们带来了许多出人意料的乐趣和惊喜。这些API可能看起来并不起眼&#xff0c;但它们却蕴含着无限的创意和趣味性。它们可以是一些小游戏API&#xff0c;让我们可以在闲暇时刻尽情娱乐&#xff1b;也可以是一些奇特的音乐API&#xff0c;…

【后端开发】服务开发场景之分布式(CAP,Raft,Gossip | API网关,分布式ID与锁 | RPC,Dubbo,Zookeeper)

【后端开发】服务开发场景之分布式&#xff08;CAP&#xff0c;Raft&#xff0c;Gossip | API网关&#xff0c;分布式ID与锁 | RPC&#xff0c;Dubbo&#xff0c;Zookeeper&#xff09; 文章目录 1、如何设计一个分布式系统&#xff1f;&#xff08;底层原理&#xff09;理论&a…

怎样清理Mac存储空间 苹果电脑内存不够用怎么办 苹果电脑内存满了怎么清理

在使用 Mac 电脑的过程中&#xff0c;用户经常会遇到磁盘空间不足的困扰&#xff0c;这时候就需要寻找有效的方法来清理苹果电脑内存了。 清理Mac存储空间可以通过多种方法进行&#xff0c;以确保你的Mac能够高效运行并释放宝贵的存储空间。以下是一些有效的清理和优化方法&am…

代码随想录第二十二天 | 654.最大二叉树, 617.合并二叉树, 700.二叉搜索树中的搜索, 98. 验证二叉搜索树

654.最大二叉树 看完想法&#xff1a;构造树一般采用的是前序遍历&#xff0c;因为先构造中间节点&#xff0c;然后递归构造左子树和右子树 确定递归函数的参数和返回值:返回TreeNode* 输入vector<int>& num; 确定终止条件:当输入数组大小1的时候&#xff0c;传入数…

数据结构和算法|排序算法系列(一)|选择排序

首先需要你对排序算法的评价维度和一个理想排序算法应该是什么样的有一个基本的认知&#xff1a; 《Hello算法之排序算法》 主要内容来自&#xff1a;Hello算法11.2 选择排序 选择排序是明显的基于比较的排序。下文开始阐述选择排序的整个算法流程 算法流程 选择排序应该已…

grpc NewClient 报错 name resolver error: produced zero addresses

场景 grpc版本: google.golang.org/grpc v1.64.0 连接客户端: import("google.golang.org/grpc""net" ) // 拿着设备ID 去获取连接 var connMap map[string]net.Conn conn, err : grpc.NewClient("device_id",grpc.WithContextDialer(func(ctx…

一致性hash算法原理图和负载均衡原理-urlhash与least_conn案例

一. 一致性hash算法原理图 4台服务器计算hash值图解 减少一台服务3台服务器计算hash值图解 增加一台服务器5台服务器计算hash值图解 二. 负载均衡原理-urlhash与least_conn 2.1.urlhash案例 # urlhash upstream tomcats {hash $requ

Spring Boot + Spring Security + JWT 从零开始

Spring Boot + Spring Security + JWT 从零开始 这篇笔记中,我们将学习如何从头开始设置一个带有Spring Security的Spring Boot应用程序,它连接到一个LDAP身份验证的Spring Security身份验证提供程序,这将是即将出现的,这个连接和工作都是开箱即用的。 实际上,设置这个非…

MySQL的安全性

给root用户设置密码 点击用户--下面三个账号双击--进行编辑 修改密码--修改完进行保存 关闭数据库后连接不上 重新编辑&#xff0c;设置密码 新建账号 填入信息--保存&#xff08;主机哪里要选择%&#xff09; 连接这个新的账号 点击连接--填写连接的名称&#xff0c;地址&…

深入理解Spring Security:保护你的Web应用程序

深入理解Spring Security:保护你的Web应用程序 这听起来像是一部詹姆斯邦德电影,邦德试图进入坏家伙的藏身之处。坏家伙设置了一系列超级安全措施,有多层次的安全防御。邦德克服了其中一层,进入了隐藏处,但又遇到了下一个陷阱。他战胜了一个又一个陷阱,最终克服了所有障…

字母的大小写转换

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;字符串对象提供了lower()方法和upper()方法进行字母的大小写转换&#xff0c;即可用于将大写字母转换为小写字母或者将小写字…

643. 子数组最大平均数 I

给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。 请你找出平均数最大且 长度为 k 的连续子数组&#xff0c;并输出该最大平均数。 任何误差小于 10-5 的答案都将被视为正确答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,12,-5,-6,50,3], k 4 输出&#xff…

2.1.2 基于配置方式使用MyBatis

文章目录 实战目标实战步骤1. 创建Maven项目2. 添加项目依赖3. 创建用户实体类4. 创建用户映射器配置文件5. 创建MyBatis配置文件6. 创建日志属性文件7. 测试用户操作8. 运行测试方法 预期结果实战方法结论 实战目标 本实战的目标是演示如何使用MyBatis框架来操作数据库。通过…

【busybox记录】【shell指令】mkdir

目录 内容来源&#xff1a; 【GUN】【mkdir】指令介绍 【busybox】【mkdir】指令介绍 【linux】【mkdir】指令介绍 使用示例&#xff1a; 创建文件夹 - 默认 创建文件夹 - 创建的同时指定文件权限 创建文件夹 - 指定多级文件路径&#xff0c;如果路径不存在&#xff0c…