贪心算法三

news2025/3/12 0:14:59

> 作者:დ旧言~
> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:了解什么是贪心算法,并且掌握贪心算法。

> 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安!

> 专栏选自:贪心算法_დ旧言~的博客-CSDN博客

> 望小伙伴们点赞👍收藏✨加关注哟💕💕

一、算法讲解

贪心算法的定义:

贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

解题的一般步骤是:

  1. 建立数学模型来描述问题;
  2. 把求解的问题分成若干个子问题;
  3. 对每一子问题求解,得到子问题的局部最优解;
  4. 把子问题的局部最优解合成原来问题的一个解。

如果大家比较了解动态规划,就会发现它们之间的相似之处。最优解问题大部分都可以拆分成一个个的子问题,把解空间的遍历视作对子问题树的遍历,则以某种形式对树整个的遍历一遍就可以求出最优解,大部分情况下这是不可行的。贪心算法和动态规划本质上是对子问题树的一种修剪,两种算法要求问题都具有的一个性质就是子问题最优性(组成最优解的每一个子问题的解,对于这个子问题本身肯定也是最优的)。

动态规划方法代表了这一类问题的一般解法,我们自底向上构造子问题的解,对每一个子树的根,求出下面每一个叶子的值,并且以其中的最优值作为自身的值,其它的值舍弃。而贪心算法是动态规划方法的一个特例,可以证明每一个子树的根的值不取决于下面叶子的值,而只取决于当前问题的状况。换句话说,不需要知道一个节点所有子树的情况,就可以求出这个节点的值。由于贪心算法的这个特性,它对解空间树的遍历不需要自底向上,而只需要自根开始,选择最优的路,一直走到底就可以了。

二、算法习题


2.1、第一题

题目链接:674. 最长连续递增序列 - 力扣(LeetCode)

题目描述:

算法思路:

找到以某个位置为起点的最⻓连续递增序列之后(设这个序列的末尾为 j 位置),接下来直接
以 j + 1 的位置为起点寻找下⼀个最⻓连续递增序列。

代码呈现:

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) 
    {
        int ret = 0, n = nums.size();
        for (int i = 0; i < n;) 
        {
            int j = i + 1;
            // 找到递增区间的末端
            while (j < n && nums[j] > nums[j - 1])
                j++;
            ret = max(ret, j - i);
            i = j; // 直接在循环中更新下⼀个位置的起点
        }
        return ret;
    }
};

2.2、第二题

题目链接:121. 买卖股票的最佳时机 - 力扣(LeetCode)

题目描述:

算法思路:

由于只能交易⼀次,所以对于某⼀个位置 i ,要想获得最⼤利润,仅需知道前⾯所有元素的最⼩
值。然后在最⼩值的位置「买⼊」股票,在当前位置「卖出」股票即可。

代码呈现:

class Solution {
public:
    int maxProfit(vector<int>& prices) 
    {
        int ret = 0; // 记录最终结果
        for (int i = 0, prevMin = INT_MAX; i < prices.size(); i++) 
        {
            ret = max(ret, prices[i] - prevMin); // 先更新结果
            prevMin = min(prevMin, prices[i]);   // 再更新最⼩值
        }
        return ret;
    }
};

2.3、第三题

题目链接:122. 买卖股票的最佳时机 II - 力扣(LeetCode)

题目描述:

算法思路:

由于可以进⾏⽆限次交易,所以只要是⼀个「上升区域」,我们就把利润拿到⼿就好了。

代码呈现:

class Solution {
public:
    int maxProfit(vector<int>& prices) 
    {
        // 实现⽅式⼆:拆分成⼀天⼀天
        int ret = 0;
        for (int i = 1; i < prices.size(); i++) 
        {
            if (prices[i] > prices[i - 1])
                ret += prices[i] - prices[i - 1];
        }
        return ret;
    }
};

2.4、第四题

题目链接:1005. K 次取反后最大化的数组和 - 力扣(LeetCode)

题目描述:

算法思路:分情况讨论,设整个数组中负数的个数为 m 个

a. m > k :把前 k ⼩负数,全部变成正数;

b. m == k :把所有的负数全部转化成正数;

c. m < k :

  • 先把所有的负数变成正数;
  • 然后根据 k - m 的奇偶分情况讨论:
  • 1. 如果是偶数,直接忽略;
    2. 如果是奇数,挑选当前数组中最⼩的数,变成负数

代码呈现:

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) 
    {
        int m = 0, minElem = INT_MAX, n = nums.size();
        for (auto x : nums) 
        {
            if (x < 0)
                m++;
            minElem = min(minElem, abs(x)); // 求绝对值最⼩的那个数
        }
        // 分类讨论
        int ret = 0;
        if (m > k) 
        {
            sort(nums.begin(), nums.end());
            for (int i = 0; i < k; i++) // 前 k ⼩个负数,变成正数
            {
                ret += -nums[i];
            }
            for (int i = k; i < n; i++) // 后⾯的数不变
            {
                ret += nums[i];
            }
        } else {
            // 把所有的负数变成正数
            for (auto x : nums)
                ret += abs(x);
            if ((k - m) % 2) // 判断是否处理最⼩的正数
            {
                ret -= minElem * 2;
            }
        }
        return ret;
    }
};

2.5、第五题

题目链接:2418. 按身高排序 - 力扣(LeetCode)

题目描述:

算法思路:

  • 我们不能直接按照 i 位置对应的 heights 来排序,因为排序过程是会移动元素的,但是names 内的元素是不会移动的。
  • 由题意可知, names 数组和 heights 数组的下标是⼀⼀对应的,因此我们可以重新创建出来⼀个下标数组,将这个下标数组按照 heights[i] 的⼤⼩排序。
  • 那么,当下标数组排完序之后,⾥⾯的顺序就相当于 heights 这个数组排完序之后的下标。之后通过排序后的下标,依次找到原来的 name ,完成对名字的排序。

代码呈现:

class Solution {
public:
    vector<string> sortPeople(vector<string>& names, vector<int>& heights) 
    {
        // 1. 创建⼀个下标数组
        int n = names.size();
        vector<int> index(n);
        for (int i = 0; i < n; i++)
            index[i] = i;
        // 2. 对下标进⾏排序
        sort(index.begin(), index.end(),
             [&](int i, int j) { return heights[i] > heights[j]; });
        // 3. 提取结果
        vector<string> ret;
        for (int i : index) {
            ret.push_back(names[i]);
        }
        return ret;
    }
};

2.6、第六题

题目链接:870. 优势洗牌 - 力扣(LeetCode)

题目描述:

算法思路:

讲⼀下⽥忌赛⻢背后包含的博弈论和贪⼼策略:
⽥忌:下等⻢ 中等⻢ 上等⻢
⻬王:下等⻢ 中等⻢ 上等⻢

  • a. ⽥忌的下等⻢ pk 不过⻬王的下等⻢,因此把这匹⻢丢去消耗⼀个⻬王的最强战⻢!
  • b. 接下来选择中等⻢ pk ⻬王的下等⻢,勉强获胜;
  • c. 最后⽤上等⻢ pk ⻬王的中等⻢,勉强获胜。

由此,我们可以得出⼀个最优的决策⽅式:

  • a. 当⼰⽅此时最差的⽐不过对⾯最差的时候,让我⽅最差的去处理掉对⾯最好的(反正要输,不如去拖掉对⾯⼀个最强的);
  • b. 当⼰⽅此时
  • c. 最差的能⽐得上对⾯最差的时候,就让两者⽐对下去(最差的都能获胜,为什么要输呢)。每次决策,都会使我⽅处于优势。

代码呈现:

class Solution {
public:
    vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) 
    {
        int n = nums1.size();
        // 1. 排序
        sort(nums1.begin(), nums1.end());
        vector<int> index2(n);
        for (int i = 0; i < n; i++)
            index2[i] = i;
        sort(index2.begin(), index2.end(),
             [&](int i, int j) { return nums2[i] < nums2[j]; });
        // 2. ⽥忌赛⻢
        vector<int> ret(n);
        int left = 0, right = n - 1;
        for (auto x : nums1) {
            if (x > nums2[index2[left]])
                ret[index2[left++]] = x;
            else
                ret[index2[right--]] = x;
        }
        return ret;
    }
};

三、结束语 

今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

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

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

相关文章

猫耳大型活动提效——组件低代码化

1. 引言 猫耳前端在开发活动的过程中&#xff0c;经历过传统的 pro code 阶段&#xff0c;即活动页面完全由前端开发编码实现&#xff0c;直到 2020 年接入公司内部的低代码活动平台&#xff0c;满足了大部分日常活动的需求&#xff0c;运营可自主配置活动并上线&#xff0c;释…

机器学习 Day02,matplotlib库绘图

1.matplotlib图像结构 容器层&#xff1a;画板&#xff0c;画布&#xff0c;坐标系辅助层&#xff1a;刻度&#xff0c;标题&#xff0c;网格&#xff0c;图例等图像层&#xff1a;折线图&#xff08;主讲&#xff09;&#xff0c;饼图&#xff0c;直方图&#xff0c;柱状图等…

MySQL中有哪几种锁?

大家好&#xff0c;我是锋哥。今天分享关于【MySQL中有哪几种锁&#xff1f;】面试题。希望对大家有帮助&#xff1b; MySQL中有哪几种锁&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 MySQL 中&#xff0c;锁是用于确保数据的一致性和并发控制的机…

Unity单例模式更新金币数据

单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。在游戏开发中&#xff0c;单例模式非常适合用于管理全局唯一的数据&#xff0c;比如玩家的金币数量。通过使用单例…

【javaEE】多线程(进阶)

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…

Vue3实战学习(Element-Plus常用组件的使用(输入框、下拉框、单选框多选框、el-image图片))(上)(5)

目录 一、Vue3工程环境配置、项目基础脚手架搭建、Vue3基础语法、Vue3集成Element-Plus的详细教程。(博客链接如下) 二、Element-Plus常用组件使用。 &#xff08;1&#xff09;el-input。(input输入框) <1>正常状态的el-input。 <2>el-input的disable状态。 <3…

C++ 链表List使用与实现:拷贝交换与高效迭代器细致讲解

目录 list的使用&#xff1a; 构造与赋值 元素访问 修改操作 容量查询 链表特有操作 拼接&#xff08;Splice&#xff09; C11 新增方法 注意&#xff1a; stl_list的模拟实现&#xff1a; 一、链表节点设计的艺术 1.1 结构体 vs 类的选择 二、迭代器实现的精髓 2…

知乎后台管理系统:数据库系统原理实验1——数据库基础概念

实验背景 通过练习绘制语义网络&#xff0c;加深对于基本概念之间关系的理解和掌握。掌握在VISIO中绘制能准确表达基本概念之间关系的语义网络的技能。了解并比较数据模型的Chen’s表示法和UML表示法。理解关系模型设计中的完整性约束的重要性。掌握在Linux操作系统下远程访问…

docker compose 以redis为例

常见docker compose 命令 》》注意这个是旧版本的&#xff0c;新版本 docker 与compose 之间没有 - 新版本的 docker compose 把 version 取消了 &#xff0c;redis 默认是没有配置文件的 &#xff0c;nginx&#xff0c;mysql 默认是有的 services:redis:image: redis:lat…

ES C++客户端安装及使用

1. ES 介绍 Elasticsearch &#xff0c; 简称 ES &#xff0c;它是个开源分布式搜索引擎&#xff0c;它的特点有&#xff1a;分布式&#xff0c;零配 置&#xff0c;自动发现&#xff0c;索引自动分片&#xff0c;索引副本机制&#xff0c; restful 风格接口&#xff0c;多…

【软件工程】一篇入门UML建模图(状态图、活动图、构件图、部署图)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;软件开发必练内功_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…

应急响应--流量分析

&#xff08;一&#xff09;Cobalt Strike流量特征分析 1.HTTP特征 源码特征&#xff1a; 在流量中&#xff0c;通过http协议的url路径&#xff0c;在checksum8解密算法计算后&#xff0c;32位的后门得到的结果是92&#xff0c;64位的后门得到的结果是93&#xff0c;该特征符…

自然语言处理:高斯混合模型

介绍 大家好&#xff0c;博主又来给大家分享知识了&#xff0c;今天给大家分享的内容是自然语言处理中的高斯混合模型。 在自然语言处理这个充满挑战与机遇的领域&#xff0c;我们常常面临海量且复杂的文本数据。如何从这些数据中挖掘出有价值的信息&#xff0c;对文本进行有…

【C++指南】一文总结C++类和对象【中】

&#x1f31f; 各位看官好&#xff0c;我是egoist2023&#xff01; &#x1f30d; 种一棵树最好是十年前&#xff0c;其次是现在&#xff01; &#x1f680; 今天来学习C类和对象的语法知识。注意&#xff1a;在本章节中&#xff0c;小编会以Date类举例 &#x1f44d; 如果觉得…

再聊 Flutter Riverpod ,注解模式下的 Riverpod 有什么特别之处,还有发展方向

三年前我们通过 《Flutter Riverpod 全面深入解析》 深入理解了 riverpod 的内部实现&#xff0c;而时隔三年之后&#xff0c;如今Riverpod 的主流模式已经是注解&#xff0c;那今天就让我们来聊聊 riverpod 的注解有什么特殊之处。 前言 在此之前&#xff0c;我们需要先回忆…

Go语言集成DeepSeek API和GoFly框架文本编辑器实现流式输出和对话(GoFly快速开发框架)

说明 本文是GoFly快速开发框架集成Go语言调用 DeepSeek API 插件&#xff0c;实现流式输出和对话功能。为了方便实现更多业务功能我们在Go服务端调用AI即DeepSeek接口&#xff0c;处理好业务后再用Gin框架实现流失流式输出到前端&#xff0c;前端使用fetch请求接收到流式的mar…

docker不停机部署

背景 最近做大疆项目时&#xff0c;后台更新部署时&#xff0c;机场和无人机就会掉线。设备自动重连注册时间比较长&#xff0c;应用长时间不可用。所以需要灰色发布服务。docker-compose的swarm模式可解决此问题。 服务构建脚本Dockerfile # 使用官方Java基础镜像&#xff…

ZLG嵌入式笔记 | ZLG核心板散热设计指引

在嵌入式系统设计中&#xff0c;散热是影响处理器性能与稳定性的关键问题。本文聚焦于高端嵌入式处理器的散热设计&#xff0c;探讨核心板的热设计与系统级热设计方法&#xff0c;以及导热材料和布局的建议&#xff0c;为解决高温问题提供参考。 用高端嵌入式处理器设计系统&am…

[Java]使用java进行JDBC编程

首先要从中央仓库下载api(类似驱动程序)&#xff0c;为了链接java和mysql 下载jar包&#xff0c;需要注意的是jar包的版本要和mysql保持一致 下面是新建文件夹lib&#xff0c;把jar包放进去&#xff0c;并添加为库 sql固定的情况下运行 import com.mysql.cj.jdbc.MysqlDataSo…

MySQL进阶-关联查询优化

采用左外连接 下面开始 EXPLAIN 分析 EXPLAIN SELECT SQL_NO_CACHE * FROM type LEFT JOIN book ON type.card book.card; 结论&#xff1a;type 有All ,代表着全表扫描&#xff0c;效率较差 添加索引优化 ALTER TABLE book ADD INDEX Y ( card); #【被驱动表】&#xff0…