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

news2024/11/24 17:40:54

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++);
            else
                ret.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++;
            else
                j++;
        }
        
        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 能够跳到位置 i
                    dp[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.coloradmin.cn/o/1714421.html

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

相关文章

【PingPong_注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

如何下载b站(哔哩哔哩bilibili)的学习视频教程

方法1&#xff1a; 打开粘贴视频链接下载即可哔哩哔哩(bilibili)视频解析下载 - 保存B站视频到手机、电脑哔哩哔哩高清视频解析下载工具是一个免费的B站视频在线解析提取工具,支持提取B站APP和bilibili网站上的任何视频,提取出来的视频无水印.我们可以借助此下载器方便地将视频…

使用jdk自带jhat工具排查OOM问题

使用jdk自带jhat工具排查OOM问题 OOM java.lang.OutOfMemoryError: Java heap space排查步骤 编写一个测试类 public class TestJVM {Testpublic void test1() throws InstantiationException, IllegalAccessException {List<A> list new ArrayList<>();for (i…

ArcGIS不同图斑设置不同的透明度

对于设置一个图层的整体的透明度&#xff0c;我们在 ArcGIS制作带蒙版的遥感影像地图http://mp.weixin.qq.com/s?__bizMzIzNjM2NTYxMg&mid2247509080&idx1&sn38dccf0a52bb3bb3758f57114ee38b72&chksme8da161bdfad9f0d363da90959a8524dcf2b60d0e8d999f8ebeef0…

OrangePi Alpro开箱体验 ubuntu 与 openEuler 实时性对比

OrangePi Alpro开箱体验 & ubuntu 与 openEuler 实时性对比 1 介绍1.1 概述1.2 OrangePi Kunpeng Pro vs OrangePi AIpro 2 开箱3 芯片介绍OrangePi AIpro(8T)Atlas 200I DK A2 4 开机连接鼠标、键盘、显示器桌面查看系统信息配置网络查看IP远程SSHWinSCP 5 GPIO Toolgpio_…

MATLAB分类与判别模型算法:基于LVQ神经网络的乳腺肿瘤诊断分类程序【含Matlab源码 MX_003期】

说明 实现基于LVQ&#xff08;Learning Vector Quantization&#xff0c;学习向量量化&#xff09;神经网络的乳腺肿瘤诊断分类任务。LVQ是一种监督学习算法&#xff0c;通常用于模式识别和分类任务。 算法思路介绍&#xff1a; 导入数据&#xff1a; 加载名为"data.mat&…

C++学习~~对于二进制文件的读写命名空间再认识异常处理

目录 1.将数据以二进制形式放到磁盘 2.将上述的数据读入内存并且显示在显示器上面 3.异常处理机制 4.抛出异常的应用实例 1.将数据以二进制形式放到磁盘 &#xff08;1&#xff09;使用student定义结构体数组stud,并对其进行初始化&#xff0c;创建输出文件流对象outfile,这…

朋友圈定时发送设置

人日常中不可缺少的一件事&#xff0c;同时也是企业用来触达客户的重要渠道&#xff0c;下面一起来了解下微信朋友圈怎么定时发送呢&#xff1f;

音乐传奇告别之作:《杰作》未解之谜❗❗

坂本龙一的《杰作》不仅是一部音乐会纪录电影&#xff0c;更是他赠予世界的一封深情告别信。 这部影片精心收录了这位音乐巨匠生前最后一场钢琴独奏音乐会的珍贵瞬间&#xff0c; 其中涵盖了《圣诞快乐&#xff0c;劳伦斯先生》、《末代皇帝》、《水》等二十首令人陶醉的经典…

设计模式20——职责链模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 职责链模式&#xff08;Chain …

手推车式电缆故障定位系统

武汉凯迪正大一体化电缆故障高压发生器用于测试各种型号的380V,600V,10kV,35kV,110kV,220kV,380kV电压等级的铜铝芯电力电缆、同轴通信电缆和市话电缆的各类故障&#xff0c;如电缆全长、开路、短路、断线、低阻故障、高阻故障、高阻泄露、高低阻抗接地、接地故障、铠装接地故障…

数据集——高分辨率图像分割成大小均匀图像(附Python代码)

将高分辨率图像分割成大小均匀的图像用于训练&#xff0c;可以提高训练效率&#xff0c;提高模型性能&#xff0c;并提供更大的灵活性。 目录 一、大小均匀图像用于训练优势二、代码2.1 代码参数修改2.2 代码2.3 输出2.4 分割结果 三、总结 一、大小均匀图像用于训练优势 内存…

3步操作助您轻松实现苹果手机照片一键传输至电脑

对于很多使用苹果手机的用户来说&#xff0c;随着手机中照片和视频数量的不断积累&#xff0c;如何将这些珍贵的回忆从手机转移到电脑&#xff0c;以便更好地保存、整理和分享&#xff0c;成为了一个值得关注的问题。那么&#xff0c;苹果手机怎么把照片导入电脑呢&#xff1f;…

职校老师的工资待遇怎么样

工资水平一直是教师们关注的焦点&#xff0c;毕竟&#xff0c;工资不仅关系到个人的生活品质&#xff0c;还影响着教师的职业满意度和工作动力。职校教师的工资待遇究竟是怎样的呢&#xff1f; 职校教师的工资水平受多种因素影响&#xff0c;包括地区、学校类型、个人资历和教学…

Qt 配置Eigen矩阵库 - 并简单测试

Qt 配置Eigen矩阵库 - 并简单测试 引言一、在Qt中配置Eigen二、低通Demo源码三、参考链接以及其他 引言 Eigen是一个开源的C模板库&#xff0c;提供了线性代数和矩阵运算的功能。它被设计为一个高性能、可扩展和易用的库&#xff0c;可以用于科学计算、机器学习和计算机图形学等…

Django 里如何使用 sqlite (操作步骤)

在 settings.py 里&#xff0c;已经设定好 sqlite 了 DATABASES {default: {ENGINE: django.db.backends.sqlite3,NAME: BASE_DIR / db.sqlite3,} }必须得设置好app # 在 settings.py 里INSTALLED_APPS [django.contrib.admin,django.contrib.auth,django.contrib.contentt…

安卓开发板_开发评估套件_4G/5G联发科MTK安卓主板定制开发

安卓开发板采用了联发科八核A53 CPU&#xff0c;主频2.0GHz&#xff0c;采用12nm制程工艺&#xff0c;拥有强大的通用计算性能。配备GE8300 GPU&#xff0c;支持1080P视频编码和H.264硬解码&#xff0c;能够解析目前流行的视频和图片格式&#xff0c;非常适合各种功能APP的测试…

16:00面试,16:08就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

封装--5.29

封装主要是封装属性&#xff0c;将改显示的显示&#xff0c;将改掩藏的掩藏&#xff08;例如&#xff1a;一个女孩20岁了&#xff0c;但是她想告诉你她18岁怎么办&#xff0c;通过封装来解决&#xff09; 编写规则&#xff1a; 定义时&#xff0c;在需要封装的属性前面加上pr…

《Navi韩语社》App:您的韩语学习与翻译的智能伴侣,支持韩文OCR文字识别提取,高精度韩语翻译!

《Navi韩语社》App&#xff0c;一款专为学习韩语和有韩语翻译需求的用户设计的多功能应用&#xff0c;它以翻译准确、功能丰富和操作简单的特点&#xff0c;成为了众多学习韩语的学生、计划去韩国旅游的背包客必备的韩语翻译工具。 &#x1f31f; 精准翻译&#xff0c;一触即达…