算法修炼之筑基篇——筑基二层后期(初步理解解决贪心算法)

news2024/11/26 17:30:25

博主:命运之光

🦄专栏:算法修炼之练气篇

🍓专栏:算法修炼之筑基篇

博主的其他文章:点击进入博主的主页

前言:学习了算法修炼之练气篇想必各位蒟蒻们的基础已经非常的扎实了,下来我们进阶到算法修炼之筑基篇的学习。筑基期和练气期难度可谓是天差地别,懂得都懂,题目难度相比起练气期的题目难度提升很多,所以要是各位蒟蒻小伙伴们看不懂筑基期的题目可以在练气期多积累积累,练气期的题目也会不断更新,大家一定要把基础打牢固了再来看筑基期的题目哈,这样子也可以提高大家的学习效率,一举两得,加油(●'◡'●)🎉🎉

 

目录

✨贪心算法到底是什么?怎么使用它?它适合于怎么样的问题?

🍓使用贪心算法时,通常遵循以下步骤:

🍓常见适合使用贪心算法的问题包括:

✨例题:删除字符

🍓题目分析

🍓先让你们看看本✨光写的💩代码

🍓对比一下在网上找到的题解

✨两个代码之间的区别。

✨贪心选择性质和最优子结构性质

✨结语


✨贪心算法到底是什么?怎么使用它?它适合于怎么样的问题?

贪心算法(Greedy Algorithm)是一种常用的算法思想,用于在每个步骤中选择局部最优解,以期望达到全局最优解。它的核心思想是通过贪心选择来构建问题的解,并希望每次选择都是最优的,以达到整体的最优解。

🍓使用贪心算法时,通常遵循以下步骤:

  1. 确定问题的最优子结构:贪心算法的关键在于问题具有最优子结构性质,即一个问题的最优解包含了其子问题的最优解。
  2. 构建贪心选择:对于每个步骤,通过某种策略选择局部最优解,这个选择通常是基于当前可用的信息,并且不考虑子问题的解决方案。
  3. 证明贪心选择性质:需要证明每次贪心选择都是最优的,即通过选择局部最优解最终可以得到全局最优解。
  4. 迭代执行贪心选择:重复执行贪心选择的步骤,直到得到全局最优解或者达到终止条件。

贪心算法适用于一些具有贪心选择性质的问题,这些问题的最优解可以通过一系列局部最优解来达到。通常情况下,贪心算法的效率较高,因为它不需要进行全局搜索,而是通过局部选择来逐步构建解决方案。

注意:并不是所有问题都适合使用贪心算法。贪心算法的局限性在于它没有回溯的能力,无法保证得到全局最优解。对于一些问题,贪心选择可能会导致局部最优解,并不能得到整体的最优解。在使用贪心算法时,需要仔细分析问题的特性,确定问题是否具有贪心选择性质,并且要能够证明贪心选择能够导致最优解。

🍓常见适合使用贪心算法的问题包括:

  • 需要在给定约束条件下寻找最优解的问题,例如零钱找零、背包问题等。
  • 可以通过选择某个局部最优解来构建整体最优解的问题,例如活动选择、区间调度等。
  • 某些问题可以转化为贪心选择的子问题,并且贪心选择是全局最优解的一部分,例如最小生成树问题中的Prim算法和Kruskal算法。

注意:贪心算法并非适用于所有问题的通用解法,对于某些问题,可能需要使用动态规划、回溯、分治等其他算法来求解。因此,在使用贪心算法时,需要充分理解问题的特点和限制,并进行合理的算法选择和设计。

✨例题:删除字符

🍓题目分析

先解释一下题目描述避免一些小伙伴们不理解

给定一个单词,请问在单词中删除 tt 个字母后,能得到的字典序最小的单词是什么?

给定一个单词,题目要求删除其中的 t 个字母后,得到的字典序(按照字母顺序)最小的单词是什么。

具体来说,题目要求在原始单词中删除 t 个字母,使得得到的新单词在字典序上尽可能靠前,也就是说新单词应该是按照字母顺序最小的。

例如,假设给定的单词是 "example",如果要删除 2 个字母,我们可以得到以下可能的新单词:

  • "eample":删除了第一个 "x" 和 "p"。
  • "exmple":删除了第二个 "a" 和 "p"。
  • "exaple":删除了 "m" 和 "p"。
  • "exale":删除了第一个 "m" 和第二个 "p"。

在这些可能的新单词中,"eample" 在字典序上最小,因为 "a" 在字母表中比 "m" 和 "x" 都靠前。因此,答案就是 "eample"。

题目的意思是找到在给定单词中删除 t 个字母后,得到字典序最小的新单词。具体删除哪些字母没有指定,可以自由选择,只需确保得到的新单词在字典序上最小。

🍓先让你们看看本✨光写的💩代码

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    char s[105],s2[105];
    int t;

    cin.getline(s, 105);  // 从标准输入读取一行字符串,并存储到s中
    cin >> t;
    
    int num=0,n=0,m=0;
    int len=strlen(s);
    int len2=strlen(s);
	while(t--)
	{
		if(s[num]<s[n+1])
		{
			s2[0]=s[num];
			n++;
			len--;
		}
		else
		{
			s2[0]=s[n+1];
			num=n+1;
			n++;
			len--;
		}
	}
	int temp=len;
	for(int i=1;i<=len;i++)
	{
		
		s2[temp--]=s[len2--];
	}
	for(int i=0;i<len;i++)
	{
		cout<<s2[i];
	}
    return 0;
}

之前有个错误是在i<len这块,应该是i<len当时写错了写成了i<=len

for(int i=0;i<len;i++)
{
    cout<<s2[i];
}

🍓对比一下在网上找到的题解


#include<iostream>
#include<list>
using namespace std;
int main(){
    int n;
    string str;
    cin>>str>>n;
    
    while(n--){
        for(int i=0;i<str.size();++i){
            if(str[i]>str[i+1]){
                str.erase(i,1);
                break;
            }
        }
    }
    cout<<str<<endl;
    return 0;    
}

🍓其中对str.erase(i,1);的应用很好(这里解释一下)
str.erase(i, 1) 是C++中string类的成员函数,用于从字符串中删除指定位置的字符。它的用法是:

str.erase(pos, count);
  • pos:表示要删除的起始位置,即从字符串的第pos个字符开始删除。
  • count:表示要删除的字符个数。

这样,str.erase(i, 1) 的意思就是从字符串 str 中删除位置为 i 的字符,删除的字符个数为 1。

例如,如果有一个字符串 str = "abcdef",执行 str.erase(2, 1),就会删除字符串中位置为 2 的字符,结果为 "abdef"

需要注意的是,删除字符会导致字符串长度减少,后面的字符会向前移动填补被删除的位置。

在贪心算法中,str.erase(i, 1) 可以用于删除字符串中的某些字符,以满足贪心选择的条件。通常,这是根据特定问题的需求来决定的,你可以根据具体问题的要求在适当的位置使用 str.erase(i, 1) 进行字符删除操作。

✨两个代码之间的区别。

代码一和代码二的主要区别在于字符串的处理方式和字符数组的使用。

代码一使用了 std::string 类型来存储字符串,并利用 std::string 提供的成员函数进行字符串操作,如 erase()size()

代码二使用了字符数组 char s[105] 来存储字符串,并利用字符数组的索引进行字符操作和字符串处理。还使用了 strlen() 函数来获取字符串的长度。

具体区别如下:

代码一:

  • 使用 std::string 类型存储字符串,可以方便地进行字符串操作。
  • 使用 std::string 提供的成员函数 erase()size() 对字符串进行删除和长度获取操作。

代码二:

  • 使用字符数组 char s[105] 存储字符串,需要手动处理字符操作和字符串处理。
  • 使用字符数组时,需要使用 strlen() 函数获取字符串的长度,没有直接的成员函数可用。

在第二段代码中,存在一些问题可能导致运行不正常:

  • len2 在赋值时与 len 的值相同,导致在后续循环中 s[len2--] 会超出数组范围。
  • s2 数组在赋值时只赋值了第一个元素 s2[0],而后续循环中没有正确赋值其他元素。
  • 输出循环中,应该使用 < len,而不是 <= len,否则会输出多余的字符。

🎉🎉做完这道题大家一定对贪心算法有了深刻的想法。就是找到局部最优解,理解题意,然后写出算法,没什么特别的地方。

有一些问题需要注意:

  1. 贪心算法的局部最优解不一定能够导致全局最优解。在某些情况下,贪心策略可能会导致次优解或无法得到正确答案。因此,在应用贪心算法时,需要确保所选取的局部最优解确实能够推导出全局最优解。
  2. 贪心算法的适用性有限。贪心算法通常适用于满足贪心选择性质和最优子结构性质的问题。贪心选择性质是指通过选择局部最优解可以得到全局最优解,最优子结构性质是指问题的最优解包含子问题的最优解。对于一些问题,贪心算法可能不适用或者需要进一步优化。

✨✨综上所述,贪心算法是一种简单而强大的解决问题的策略,但在应用时需要确保问题满足贪心选择性质和最优子结构性质,并且需要仔细分析问题的特点,选择合适的贪心策略。

✨贪心选择性质和最优子结构性质

当应用贪心算法解决问题时,有两个重要的概念需要考虑:贪心选择性质和最优子结构性质。

  1. 贪心选择性质(Greedy Choice Property): 贪心选择性质是指在每一步选择中,选择当前看起来最优的解决方案。也就是说,贪心算法做出的每个局部决策都应该是当前状态下最好的选择,而不考虑未来步骤的影响。这样,通过一系列局部最优解,希望能够得到全局最优解。
  2. 最优子结构性质(Optimal Substructure Property): 最优子结构性质是指问题的最优解包含子问题的最优解。也就是说,问题的整体最优解可以通过子问题的最优解推导得出。这种性质允许我们通过解决子问题来构建问题的最优解,从而简化问题的求解过程。

对于一个问题适用贪心算法,需要满足以下两个条件:

  1. 贪心选择性质:每一步选择都是局部最优的选择,可以得到全局最优解。
  2. 最优子结构性质:问题的最优解包含子问题的最优解,可以通过解决子问题来构建问题的最优解。

在应用贪心算法时,需要仔细分析问题的特点和约束条件,并选择合适的贪心策略。这意味着需要理解问题的本质,识别出问题中哪些部分具有贪心选择性质和最优子结构性质,以便设计相应的贪心策略。

选择合适的贪心策略可能需要考虑问题的特征、约束条件、目标函数以及可能的局部最优解如何导致全局最优解。有时候可能需要尝试不同的贪心策略或结合其他算法技巧来解决问题。

✨结语

总结来说,贪心算法要求问题具有贪心选择性质和最优子结构性质,并需要仔细分析问题的特点和约束条件,选择合适的贪心策略。这样才能确保贪心算法能够正确解决问题并得到全局最优解。

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

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

相关文章

【opencv】无法打开源文件opencv.hpp | bug记录

问题描述 今天这个bug其实比较搞笑&#xff1a; 原因分析&#xff1a; 那就是我们的VS软件没有识别到安装的库。肯定是下面三个环节哪里出错了&#xff1a; 1&#xff09;项目属性里的包含目录&#xff08;include&#xff09; 2&#xff09;项目属性里的库目录(lib) 3&…

随笔记录阿里云开发者社区Java开发高级技能自测20道题

目录 【单选】1.MyBatis中&#xff0c;主要使用哪个Java 接口来执行SQL命令&#xff1f;【单选】2.Spring中ApplicationContext的主要用法是&#xff1f;【单选】3.MySQL中&#xff0c;使用正则表达式查找news表中title以S或Q或L字母开头的所有数据&#xff0c;语句是&#xff…

【MySql】MySql的数据类型

文章目录 数据类型分类数值类型tinyint类型bit类型小数类型floatdecimal 字符串类型charvarchar日期和时间类型enum和set 数据类型分类 对于数据类型分类&#xff0c;这里简单分为数值类型&#xff08;如BIT,BOOL,INT&#xff09;&#xff0c;文本、二进制类型&#xff08;如CH…

JMeter 测试 ActiveMq

JMeter 测试 ActiveMq 的资料非常少&#xff0c; 我花了大量的时间才研究出来 关于ActiveMq 的文章请参考我另外的文章。 版本号: ActiveMq 版本号: 5.91 Jmeter 版本号: 1.13 添加ActiveMq 的jar包 将 ActiveMq 下的 "activemq-all-5.9.1.jar" 复制…

labelme安装与打包为独立exe程序(超级详细版!!!!)

文章目录 labelme安装与打包为独立exe安装打包以上全部命令直接复制粘贴就行&#xff01;&#xff01;&#xff01;&#xff01; labelme安装与打包为独立exe 按照官网给出的详细教程即可&#xff0c;不用去看一些博客&#xff08;都过时了&#xff09;。。。label官网 简要说…

Linux操作

Linux操作 一、Linux操作 1.安装yum包&#xff1a; $ yum install PACKAGE_NAME yum install mysql2.取出yum包装&#xff1a; $ yum remove PACKAGE_NAME yum remove mysql3.重新安装一个yum包&#xff1a; $ yum reinstall PACKAGE_NAME yum reinstall mysql4.搜索yum包…

tb6612电机驱动软件开发(cubeide工程调试,引脚等设置)

tb6612电机驱动软件开发(cubeide工程调试&#xff0c;引脚等设置&#xff09; 文章目录 tb6612电机驱动软件开发(cubeide工程调试&#xff0c;引脚等设置&#xff09;CLOCK(RCC)SYSGPIONVICTimer定时器配置PWM输出设置电机转速定时器编码模式普通定时器 UART串口设置 CLOCK(RCC…

unittest测试框架详解

单元测试的定义 1. 什么是单元测试&#xff1f; ​ 单元测试是指&#xff0c;对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作&#xff0c;这里的最小可测试单元通常是指函数或者类&#xff0c;一般是开发来做的&#xff0c;按照测试阶段来分&a…

Vue实现锁屏功能

这两天刚做了个新需求&#xff0c;要做个系统锁屏&#xff08;当然锁的是当前的系统&#xff09;&#xff0c;就类似于电脑锁屏似的。 共两种情况下锁屏&#xff0c;一种是无操作一定时间后自动锁屏&#xff1b;第二种是可以按下组合键&#xff08;快捷键&#xff09;主动进行锁…

利用ThreadLocal+AOP切面编程实现RPC日志

前言 最近在稍微学了一下ThreadLocal以及它的使用场景&#xff0c;同时也学了一下AOP相关的内容&#xff0c;刚好做个很常见的RPC日志来练练手。 主要思想是通过切面来拦截所有的请求&#xff0c;在请求进入切面的时候&#xff0c;可以用ThreadLocal来存储当前请求的线程专属的…

微信小程序基础使用

微信小程序的基本使用 微信小程序文件类型 微信小程序主要提供了 4 种文件类型&#xff1a; 类型名称作用是否必须存在.wxml用于页面的布局结构&#xff0c;相当于网页中 .html 文件是.wxss用于页面的样式&#xff0c;相当于网页中的 .css 文件否.js用于页面的逻辑是.json用…

springboot期末随笔,随缘随缘啊哈哈

一、使用ImportResource加载XML配置文件示例&#xff1a; 创建一个XML配置文件&#xff0c;命名为person.xml&#xff0c;在文件中定义一个Person类的bean&#xff1a; <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.…

腾讯云轻量应用服务器是什么?和CVM云服务器有什么区别?

腾讯云轻量应用服务器是什么&#xff1f;腾讯云轻量服务器和云服务器有什么区别&#xff1f;为什么轻量应用服务器费用更低&#xff1f;是因为轻量服务器CPU内存性能比云服务器CVM性能差吗&#xff1f;轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程…

(浙大陈越版)数据结构 第三章 树(中) 二叉搜索树和平衡二叉树

目录 4.1.1 二叉搜索树及查找 什么是二叉搜索树 定义 二叉搜索树特殊函数集&#xff1a; 查找操作&#xff1a;Find 算法思想 代码实现 补&#xff1a;查找最大和最小元素 4.1.2 二叉搜索树的插入 插入操作&#xff1a;Insert 算法思想 代码实现 例题 4.1.3 二叉…

JavaSE_day49-50(XML,DTD约束,schema约束,解析XML,DOM实现解析XML文件)

注意&#xff1a;学习下面内容需要参考那个文档w3cschool&#xff08;学习Java资源&#xff09;&#xff0c;Gitee上传&#xff01; 1 Xml格式&#xff1a; <?xml version"1.0" encoding"UTF-8"?><!-- 这是注释--><Students><stude…

【MySQL数据库 | 第十三篇】多表查询

前言&#xff1a; 多表查询是指在一个SQL语句中使用多个表进行数据查询和操作。多表查询可以对数据表之间的关系进行查询&#xff0c;例如可以通过连接多个表来获取更完整的数据信息。关于单表查询我们也介绍过&#xff0c;已经整理成文章发布&#xff1a;【MySQL数据库 | 第九…

vue2模板渲染更新详细流程

vue2模板渲染更新详细流程 此文章基于vue2.6.10版本进行解析&#xff0c;在看文章最好结合源码一起看能帮助更快的理解。 在vue中会将.vue文件或者template属性解析成一个render函数&#xff0c;在渲染&#xff08;调用$mount方法&#xff09;的时候通过执行这个render函数生…

#systemverilog# 关于流操作符>>和<<引发的思考

前言 对于流操作符&#xff0c;相比大家都不陌生&#xff0c;在实际项目中运用特别广泛。今天我们通过几个小例子&#xff0c;来回顾和深层认识一下该操作符。 概念 流操作符&#xff08;bit-stream&#xff09;&#xff0c;表示方式为{>>{}} 和 {<<{}}。前者会…

spring源码 IoC 之xml配置bean注册解析的 BeanDefinitions

概述 IoC 容器的初始化过程分为三步骤&#xff1a;Resource 定位、BeanDefinition 的载入和解析&#xff0c;BeanDefinition 注册 1、Resource 定位。我们一般用外部资源来描述 Bean 对象&#xff0c;所以在初始化 IoC 容器的第一步就是需要定位这个外部资源 2、BeanDefinition…

opencv4 傅里叶变换

傅里叶变换 ① 高频&#xff1a;变化剧烈的灰度分量&#xff0c;例如边界礁石。 ② 低频&#xff1a;变化缓慢的灰度分量&#xff0c;例如一片大海。 ③ 高通滤波器&#xff1a;只保留高频&#xff0c;会使得图像细节增强。高频边界锐化了&#xff0c;增强了&#xff0c;细节…