【夜深人静学习数据结构与算法 | 第六篇】贪心算法

news2024/11/27 4:16:56

目录

前言:

引入:

贪心算法:    

455. 分发饼干 - 力扣(LeetCode)

376. 摆动序列 - 力扣(LeetCode)

53. 最大子数组和 - 力扣(LeetCode)

122. 买卖股票的最佳时机 II - 力扣(LeetCode)


前言:

        在本文我们将为大家介绍在计算机中比较常见的一种算法:贪心算法。他并没有具体的代码实现后者是方法套路,而是一种简单,高效的思维方式,因此需要我们以学习思维方式为辅,练习题目为主,这样才可以更加高效的掌握贪心算法。

引入:

         请各位思考一下:如果我们想要在大学的期末考试中取得一个好成绩,我们应该怎么办呢?我们应该学好每一课,那又要如何学好每一科呢?那就要每一节课认真听讲,做好练习。换句话来讲:我们要想取得好的成绩,就要每一天都达成一个最好的学习状态。而在这之中,就蕴藏着贪心算法的思想:通过一个个局部最优解达成全局最优解

贪心算法:    

        贪心算法(Greedy Algorithm)是一种简单而常见的算法思想。它的基本思想是在每一步选择中都采取在当前状态下最好或最优的选择,从而希望导致结果是全局最优或最好的算法。贪心算法的优点是简单、高效,适用于一些特定问题的求解。

        贪心算法一般分为两种类型:纯贪心和分数规划贪心。前者的策略是每次选择当前看起来最优的决策,而后者则是将问题转化为一系列子问题,每个子问题都能通过贪心算法得到最优解,从而构造出全局最优解。

        贪心算法虽然简单易懂,但并不是所有问题都适合用贪心算法求解。有时候贪心策略下的局部最优解可能并不是全局最优解,需要通过其他算法来优化解决方案。

假设此时你的面前有一堆钞票,你只能取十张,那么如何取十张之后得到的金额最大呢?

        只需要每一次都取单张面额最大的纸币,这样我们连续取十张之后,就可以得到最大的金额,这种在通过一个个局部最优解达成全局最优解的策略,就是贪心算法。 

        贪心算法类的题目就像是英语的阅读题一样他无固定套路,没有固定的局部最优解,很多题要么一眼有思路,要么很难想出思路,而不同题目之间的局部最优解也没有什么共通性,只能通过多刷题和多见题来掌握贪心算法。

 我们在下面就通过力扣算法题来给向大家展示贪心算法

455. 分发饼干 - 力扣(LeetCode)

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

 解题思路:想要达到喂饱更多的小孩这个全局最优解,我们就要想到:只要喂给每一个孩子的饼干都是最符合他的就可以达到这个目标例如此时我们有 5  8  两个孩子,有6,9两个饼干,我们如果把6饼干喂给5小孩,把9喂给8小孩就可以维保两个孩子,但是如果把9喂给5小孩,那8小孩就无法喂饱,也就无法达成喂饱小孩最多的目标。也就是我们尽量用大饼干喂大胃口小孩,小饼干喂小胃口小孩

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(s.begin(), s.end(), greater());
        sort(g.begin(), g.end(), greater());
        
        int count = 0;
        int j = 0;
        int i = 0;
        while (i < g.size() && j < s.size()) {
            //此前饼干可以喂饱孩子
            if (s[j] >= g[i]) {
                count++;
                i++;
                j++;
            } 
            //饼干喂不饱孩子
            else {
                i++;//换下一个孩子
                //此时不换饼干是因为饼干大小排序是从大到小,
                //既然此时的饼干已经无法喂饱当前小孩,那后面的饼干也不可能喂饱,因此只用看下一个小孩。
            }
        }
        return count;
    }
};

看到这里大家可能会想:不是吧,这种简单思路还要专门建立一个算法种类。其实不然,贪心算法题就是两个极端:简单的题很简单,难的题很难。感兴趣的同学可以搜索一下力扣968题:监督二叉树,可以说是比较典型的一道贪心算法难题

376. 摆动序列 - 力扣(LeetCode)

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。

例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。

相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。

题目中举的这个例子不明显,我们自己定义一个数组来看:

[1,17,5,10,13,15,10,5,16,8]

 

如果我们想要达到差值始终正负出现,我们就删掉所有的单调子数组。

这样我们就可以得到最长的摆动序列,但其实这只是一个底层思路

实际上,我们连删除的操作都不用做,因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)

这就是贪心所贪的地方,让峰值尽可能的保持峰值,然后删除单一坡度上的节点

代码实现:

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if (nums.size() <= 1) return nums.size();
        int curDiff = 0; // 当前一对差值
        int preDiff = 0; // 前一对差值
        int result = 1;  // 记录峰值个数,序列默认序列最右边有一个峰值
        for (int i = 0; i < nums.size() - 1; i++) {
            curDiff = nums[i + 1] - nums[i];
            // 出现峰值
            if ((preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)) {
                result++;
                preDiff = curDiff; // 注意这里,只在摆动变化的时候更新prediff
            }
        }
        return result;
    }
};

53. 最大子数组和 - 力扣(LeetCode)

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

解题思路:我们要想达成子数组和最大这个全局最优解,就要达到每一步是符合要求内的最大值,其实很好理解: sum=sum+nums[i],我们要想使得sum最大,就应该尽量保证他不是负数,换句话说:我们如果前面的sum已经是一个负数了,负数+num[i],那么我们就抛弃sum[i],让子数组的头从sum[i]重新开始这样往后面看并且添加一个计数器,记录最大的sum,最终返回这个计数器就可以,这样就可以一个for循环结束满足整个要求,大大降低了时间复杂度。

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
      
        int sum=0;
        int i=0;
        int count=INT32_MIN;;
        while(i<nums.size())
        {
            if(sum<=0)
            {
                sum=nums[i];
                i++;
                if(sum>count)
              {
                count=sum;
              }
                continue;
            }
            sum=sum+nums[i];
            i++;
            if(sum>count)
            {
                count=sum;
            }
        }
        return count;
    }
};

122. 买卖股票的最佳时机 II - 力扣(LeetCode)

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

 解题思路:我们要想总收益最高,那么就是只获得正收益,股票价格一跌就赶紧出手,这样就可以得到最高的收益,在这个题里面就是如果第二天亏损,那么我们就出售股票,如果第二天赚钱,我们就买入股票。

例如我们的例题:

        7 1 5 3 6 4

        第二天:价格为1,相比昨天下降6元

        第三天:价格为5,相比昨天上涨五元

        第四天:价格为3,相比昨天亏损二元(既然亏损,那么我们就五元的时候卖出,就可以得到正收益。)

        第五天:价格为6,相比较昨天上涨三元(既然上涨我们就在昨天三元买入)

        第六天:价格为4,相比较昨天下跌四元(既然下跌我们就在昨天六元的时候卖出)

 我们只需要收集正收益就可以了,甚至不用记录哪一天买入,只需要一个数组存储正收益,后面把正收益一加起来就好了。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<int>d1;
        int sum=0;
        for(int i=0;i<prices.size()-1;i++)
        {
            d1.push_back(prices[i+1]-prices[i]);
        }
        for(int a : d1)
        {
            if(a>0)
            {
                sum+=a;
            }
        }
        return sum;
    }
};

总结:

        贪心算法是一种解题思路,他没有套路可以总结,没有解题模板,没有固定格式,但是在一些题中,如果我们可以利用贪心算法思路把这道题的头绪理清楚,那么代码将会是很简洁高效的,因此希望大家可以多刷一些关于贪心算法的题目。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

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

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

相关文章

【Python 随练】统计字符类型个数

题目&#xff1a; 输入一行字符&#xff0c;分别统计出其中英文字母、空格、数字和其它字符的个数。 简介&#xff1a; 在本篇博客中&#xff0c;我们将解决一个字符统计问题&#xff1a;输入一行字符&#xff0c;统计其中英文字母、空格、数字和其他字符的个数。我们将提供…

学习python爬虫需要掌握哪些库?

Python爬虫是指使用Python编写的程序&#xff0c;用来自动化地获取互联网上的数据。通过爬取网站的HTML内容&#xff0c;并解析和提取所需的数据&#xff0c;可以实现自动化地收集、分析和处理大量的在线数据。 学习Python爬虫需要掌握以下几个核心库&#xff1a; Requests&am…

【ARM AMBA AXI 入门 9 - AXI 总线 AxPROT 与安全之间的关系 】

文章目录 介绍ARM Trustzone的安全扩展简介 1.1 AXI AxPROT 介绍1.1.1 AXI 对 Trustzone的支持 介绍 ARMv8 架构中的AXI&#xff08;Advanced eXtensible Interface&#xff09;总线与NS&#xff08;Non-Secure&#xff09;位密切相关。NS位是指在ARM TrustZone安全扩展中定义…

LeetCode 1254. Number of Closed Islands【DFS,BFS,并查集】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

单片机MCU如何实现让部分代码运行在RAM中

随着单片机硬件的发展&#xff0c;其中的RAM和flash越做越大。MCU在实际的使用中&#xff0c;通常程序都是运行在flash上的&#xff0c;RAM的高速空间并没有得到充分的利用&#xff0c;如果我们的程序需要运行的更快&#xff0c;系统有更好的实时性&#xff0c;我们可以考虑将这…

CSS查缺补漏之《常用长度单位(px、em、rem、%、vw/vh、vmin/vmax)》

此文内容较少&#xff0c;轻轻松松掌握&#xff0c;莫要有压力~ 正如现实生活中长度具有mm、dm、cm、m等&#xff0c;在css中&#xff0c;也具备多种长度单位&#xff0c;本文对常用的几种单位进行详细举例介绍~ px&#xff1a;像素单位 初学css时&#xff0c;px单位经常被使用…

【Leetcode60天带刷】day08字符串——344.反转字符串, 541. 反转字符串II,剑指Offer 05.替换空格,151.翻转字符串里的单词

题目&#xff1a; 344. 反转字符串 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1&#xff1a; 输入&…

基于SpringBoot+Vue的“漫画之家”系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

新电脑机环境安装笔记

「Navicat_15.0.25_64bit_Setup.exe」 下载https://www.aliyundrive.com/s/b9xUw2JpuJb Navicat Keygen Patch v5.6.0 下载 https://www.aliyundrive.com/s/YYyE5BQMMuN 全程断网操作 patch 将安装目录选中 提示 check 64 mysql安装&#xff1a; https://baijiahao.baidu…

因子分析——SPSS实例分析

【续上篇主成分分析】 因子分析常用于通过可观测变量推断出其背后的公共因子&#xff08;也称为隐变量&#xff09;&#xff0c;样本在公共因子上的取值变化影响其在可观测变量上的取值&#xff0c;因为一般公共因子的个数小于可观测变量的数目&#xff0c;所以因子分析也可以…

渠道归因(一)传统渠道归因

渠道归因&#xff08;一&#xff09;传统渠道归因 小P&#xff1a;小H&#xff0c;我又来了。。。最近在做ROI数据&#xff0c;但是有个问题。。。 小H&#xff1a;什么问题&#xff0c;不就是收入/成本吗&#xff1f; 小P&#xff1a;是的&#xff0c;每个渠道的成本很容易计算…

基于html+css的图展示134

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

如何打造创意百变的虚拟直播场景?

场景对于直播来说是直接呈现给观众的&#xff0c;也是直播带货的“直接”的视觉冲击的价值核心&#xff0c;所以场景的设计十分重要。今天&#xff0c;我们就一起来看看如何低成本搭建一个网红同款直播间吧&#xff01; 直播间类型 直播间大体可以分为三种类型&#xff1a;虚拟…

CUDA共享内存详解

为什么需要共享内存&#xff1f; 共享内存的访问速度比访问全局速度快的多&#xff0c;因此对于多次访问全局内存的程序&#xff0c;特别是需要多次将全局内存的运算结果缓存到全局内存的运算&#xff0c;先将临时结果缓存到共享内存再做计算&#xff0c;会提高运算速度。 1、…

C语言使用Wininet库网络编程跳坑记 —— cookies篇

笔者尝试C语言使用Wininet库进行网络编程时&#xff0c;我尝试使用 InternetSetCookieA() 或 HttpAddRequestHeadersA() 设置 cookie。 HttpAddRequestHeadersA(Request, headers, header_len, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE); InternetSetCookieA(url, NU…

基于SpringBoot+Vue的电影分享平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 当代社会&#xff0c;…

Linux(环境准备)VMware与CentOS及XShell的安装

目录 第 1 章 VMware 1.1 VMware 安装 1.1.1 VMware Workstation Pro 15.5 安装包 ​1.2.2 欢迎界面 1.2.3 同意许可证 1.2.4 选择安装路径 1.2.5 用户体检计划 1.2.6 快捷方式 1.2.7 开始安装 1.2.8 等待安装完成 1.2.9 安装完成 1.2.10 输入许可证 1.2.11 VM…

工欲善其事,必先利其器--Vscode嵌入式Linux开发远程开发设置(适用于多平台)

点击上方“嵌入式应用研究院”&#xff0c;选择“置顶/星标公众号” 干货福利&#xff0c;第一时间送达&#xff01; 来源 | 嵌入式应用研究院 整理&排版 | 嵌入式应用研究院 最近搭了一台Ubuntu18.04版本的桌面PC&#xff0c;不得不说比起Window搭虚拟机搞起来爽多了&…

python文件首行

类似于一切脚本文件一样&#xff0c;首行可用于指定解释器用于执行文件&#xff1b; 常见的是linux系统下的各个解释器。比如&#xff1a; #!/bin/sh– 使用Bourne shell或兼容的 shell执行文件&#xff0c;假定位于 /bin 目录中#!/bin/bash– 使用Bash shell执行文件#!/usr/…

会声会影如何抠图换背景 会声会影抠图后人物变透明

抠图换背景&#xff0c;大家可能会在图片编辑上应用得比较多。实际上&#xff0c;视频也能通过抠图的方式换背景&#xff0c;其困难程度与背景类型有关。纯色背景会比较简单&#xff0c;非纯色背景会比较难&#xff0c;接下来&#xff0c;一起来看看会声会影如何抠图换背景&…