算法训练day31贪心算法理论基础Leetcode455分发饼干376摆动序列53最大子序和
贪心算法理论基础
文章链接
代码随想录 (programmercarl.com)
说实话贪心算法并没有固定的套路。最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧。
面试中基本不会让面试者现场证明贪心的合理性,代码写出来跑过测试用例即可,或者自己能自圆其说理由就行了。
刷题或者面试的时候,手动模拟一下感觉可以局部最优推出整体最优,而且想不到反例,那么就试一试贪心。
因为贪心有时候就是常识性的推导,所以会认为本应该就这么做!
贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法策略。简而言之,贪心算法不从整体最优解考虑,它所做出的选择只在某种意义上是局部最优的。贪心算法试图找到一个全局最优解的快速途径,但没有保证会得到最佳解。
贪心算法的特点:
1. **局部最优选择**:在每一步选择中,它都采取当前状态下的最优解,不会考虑整个问题的全局最优解。
2. **无回溯**:一旦作出这些选择,就不再回溯,即不考虑以前的选择。
3. **实现简单**:相对于其他算法,如动态规划,贪心算法通常更简单,易于实现。
4. **求解速度快**:由于每步都采取局部最优解,不需要考虑其他可能的解,因此在某些问题上可以更快地得到解答。
贪心算法适用于问题满足两个主要条件:贪心选择性质和最优子结构。贪心选择性质意味着通过做出局部最优选择,我们可以得到全局最优解。最优子结构意味着问题的最优解包含其子问题的最优解。
然而,并不是所有问题都可以用贪心算法有效解决。对于那些不能确保通过局部最优解最终达到全局最优解的问题,贪心算法可能不会得到最优解。
应用实例包括:
- **哈夫曼编码**:用于数据压缩的哈夫曼树构建。
- **最小生成树**:如Prim和Kruskal算法。
- **任务调度问题**:例如,有限资源下的任务调度以最小化总完成时间或最大化完成的任务数。
- **找零问题**:在提供最少硬币数目方面,对于特定面额的货币体系,贪心算法能给出最优解。
贪心算法简单且强大,但其应用范围有限,需要仔细分析问题是否适合采用贪心策略。
贪心一般解题步骤
贪心算法一般分为如下四步:
- 将问题分解为若干个子问题
- 找出适合的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解堆叠成全局最优解
这个四步其实过于理论化了,我们平时在做贪心类的题目 很难去按照这四步去思考,真是有点“鸡肋”。
做题的时候,只要想清楚 局部最优 是什么,如果推导出全局最优,其实就够了
不好意思了,贪心没有套路,说白了就是常识性推导加上举反例。
455 分发饼干
题目描述
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例 1:
输入: g = [1,2,3], s = [1,1] 输出: 1 解释: 你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。 虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 所以你应该输出1。
示例 2:
输入: g = [1,2], s = [1,2,3] 输出: 2 解释: 你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。 你拥有的饼干数量和尺寸都足以让所有孩子满足。 所以你应该输出2.
提示:
1 <= g.length <= 3 * 1040 <= s.length <= 3 * 1041 <= g[i], s[j] <= 231 - 1
题目分析
这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。
可以尝试使用贪心策略,先将饼干数组和小孩数组排序。
然后从后向前遍历小孩数组,用大饼干优先满足胃口大的,并统计满足小孩数量。
acm模式代码
#include <iostream>
#include <vector>
#include <algorithm>class Solution {
public:int findContentChildren(std::vector<int>& g, std::vector<int>& s) {int result = 0;std::sort(g.begin(), g.end());std::sort(s.begin(), s.end());int index = s.size() - 1; //饼干数组下标for (int i = g.size() - 1 ; i >= 0; i--) { //遍历胃口while(index >= 0 && s[index] >= g[i]) {// 遍历饼干result ++;index --;break;}}return result;}
};int main() {Solution sol;std::vector<int> g = {1,2};std::vector<int> s = {1,2,3};int result = sol.findContentChildren(g, s);std::cout << result << std::endl;return 0;
}
376 摆动序列
题目描述
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。
-
例如,
[1, 7, 4, 9, 2, 5]是一个 摆动序列 ,因为差值(6, -3, 5, -7, 3)是正负交替出现的。 - 相反,
[1, 4, 7, 2, 5]和[1, 7, 4, 5, 5]不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。
给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。
示例 1:
输入:nums = [1,7,4,9,2,5] 输出:6 解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3) 。
示例 2:
输入:nums = [1,17,5,10,13,15,10,5,16,8] 输出:7 解释:这个序列包含几个长度为 7 摆动序列。 其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。
示例 3:
输入:nums = [1,2,3,4,5,6,7,8,9] 输出:2
提示:
1 <= nums.length <= 10000 <= nums[i] <= 1000
进阶:你能否用 O(n) 时间复杂度完成此题?
题目分析
局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。
整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。
实际操作上,其实连删除的操作都不用做,因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)
这就是贪心所贪的地方,让峰值尽可能的保持峰值,然后删除单一坡度上的节点
这是我们思考本题的一个大题思路,但本题要考虑三种情况:
- 情况一:上下坡中有平坡
- 情况二:数组首尾两端
- 情况三:单调坡中有平坡
本题异常情况的本质,就是要考虑平坡, 平坡分两种,一个是 上下中间有平坡,一个是单调有平
acm模式代码
#include <iostream>
#include <vector>class Solution {
public:int wiggleMaxLength(std::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;}
};int main () {std::vector<int> nums = {1,17,5,10,13,15,10,5,16,8};Solution sol;int result = sol.wiggleMaxLength(nums);std::cout << result << std::endl;return 0;
}
53 最大子序列
题目描述
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1] 输出:1
示例 3:
输入:nums = [5,4,-1,7,8] 输出:23
提示:
1 <= nums.length <= 105-104 <= nums[i] <= 104
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。
题目分析
局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。
全局最优:选取最大“连续和”
局部最优的情况下,并记录最大的“连续和”,可以推出全局最优。
acm模式代码
#include <iostream>
#include <vector>class Solution {
public:int maxSubArray(std::vector<int>& nums) {int count = 0;int result = 0;for (int i = 0; i < nums.size(); i++) {count += nums[i];if (count > result) { // 取区间累计的最大值(相当于不断确定最大子序终止位置)result = count;}if (count < 0) {count = 0; // 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和}}return result;}
};int main () {std::vector<int> nums = {-2,1,-3,4,-1,2,1,-5,4};Solution sol;int result = sol.maxSubArray(nums);std::cout << result << std::endl;return 0;
}
相关文章:
算法训练day31贪心算法理论基础Leetcode455分发饼干376摆动序列53最大子序和
贪心算法理论基础 文章链接 代码随想录 (programmercarl.com) 说实话贪心算法并没有固定的套路。最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧。 面试中基本不会让面试者现场证明贪心的合理性,代码写出来跑过测试用例即可&…...
Java与JavaScript同源不同性
Java是目前编程领域使用非常广泛的编程语言,相较于JavaScript,Java更被人们熟知。很多Java程序员想学门脚本语言,一看JavaScript和Java这么像,很有亲切感,那干脆就学它了,这也间接的帮助了JavaScript的发展…...
【JavaEE】spring boot快速上手
SpringBoot快速上手 文章目录 SpringBoot快速上手Maven会出现的一个官方bug创建完项目之后常用的的三个功能依赖管理Maven仓库中央仓库本地仓库国内源配置私服 springboot项目创建什么是springspring boot项目的创建Hello Worldweb服务器 SpringMVC什么是SpringWebMVC什么是MVC…...
【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历)
二叉树 一个二叉树是一个有穷的结点集合。 它是由根节点和称为其左子树和右子树的两个不相交的二叉树组成的。 二叉树可具有以下5种形态。 性质 一个二叉树第i层的最大结点数为 2 i − 1 2^{i-1} 2i−1, i ≥ 1 i \geq 1 i≥1 每层最大结点可以对应完美二叉树(…...
GPT SOVITS项目 一分钟克隆 (文字输出)
步骤流程:(首先使用UVR 提取人声文件,然后按下面步骤进行) 注意这里提交的音频是参考的音频...
python34-Python列表和元组之加法
列表和元组支持加法运算,加法的和就是两个列表或元组所包含的元素的总和。 需要指出的是,列表只能和列表相加;元组只能和元组相加;元组不能直接和列表相加。 如下代码示范了元组和列表的加法运算。 # !/usr/bin/env python# -*- coding: utf-8 -*-# T…...
不做程序员了(转岗半年后对程序员岗位的思考)
不做程序员了(转岗半年后对程序员岗位的思考) 前言 好久没有更新了,已经久到CSDN的小编来问我为什么不更了。原因是我半年前转岗了,不再做程序员了,由程序员变为了产品经理。废话不多说,换个视角来给大家…...
DS:八大排序之直接插入排序、希尔排序和选择排序
创作不易,感谢三连支持!! 一、排序的概念及运用 1.1 排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起 来的操作。稳定性&…...
【MySQL】-21 MySQL综合-8(MySQL默认值+MySQL非空约束+MySQL查看表中的约束)
MySQL默认值MySQL非空约束MySQL查看表中的约束 MySQL默认值在创建表时设置默认值约束在修改表MySQL默认值在创建表时设置默认值约束在修改表时添加默认值约束删除默认值约束删除默认值约束 MySQL非空约束在创建表时设置非空约束在修改表时添加非空约束删除非空约束 MySQL查看表…...
力扣hot3--并查集+哈希
第一想法是排个序然后遍历一遍,but时间复杂度就超啦 并查集居然与哈希结合了() 已经好久没用过并查集了,,,我们用哈希表f_node中来记录原结点的父节点,其中key是原结点,value是父节点…...
微信网页版能够使用(会顶掉微信app的登陆)
一、文件结构 新建目录chrome新建icons,其中图片你自己找吧新建文件manifest.json新建文件wx-rules.json 二、文件内容 对应的png你们自己改下 1、manifest.json {"manifest_version": 3,"name": "wechat-need-web","author…...
word软件中硬件图像加速有什么用处?禁用硬件图形加速(G)会影响word文档中插入图片的分辨率吗?
问题描述:word软件中硬件图像加速有什么用处?禁用硬件图形加速(G)会影响word文档中插入图片的分辨率吗? 问题解答: 在 Microsoft Word 中,硬件图形加速主要用于提高图形元素的渲染速度和性能,特别是处理大…...
.NET Core MongoDB数据仓储和工作单元模式封装
前言 上一章我们把系统所需要的MongoDB集合设计好了,这一章我们的主要任务是使用.NET Core应用程序连接MongoDB并且封装MongoDB数据仓储和工作单元模式,因为本章内容涵盖的有点多关于仓储和工作单元的使用就放到下一章节中讲解了。仓储模式(R…...
lua:有关表访问的metamethod
针对在两种正常状态:表的不存在的域的查询和修改,Lua也提供了改变 tables的行为的方法。 index metamethod 我们可以通过index元方法来实现访问table内部不存在的域时人为操控返回数据。 比如以下测试代码: local set {1,2,3} setmetata…...
【MySQL】索引事务
MySQL索引事务 1. 索引1.1 概念1.2 作用1.3 使用场景1.4 使用1.5 案例 2. 事务2.2 事物的概念2.3 使用 3. 内容重点总结 1. 索引 1.1 概念 索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引, 并指定索引的类…...
ChatGPT重大升级:能自动记住用户的习惯和喜好,用户有权决定是否共享数据给OpenAI
OpenAI刚刚宣布了ChatGPT的一项激动人心的更新! OpenAI在ChatGPT中新加了记忆功能和用户控制选项,这意味着GPT能够在与用户的互动中记住之前的对话内容,并利用这些信息在后续的交谈中提供更加相关和定制化的回答。 这一功能目前正处于测试阶…...
CSS设置盒子阴影
语法 box-shadow: *h-shadow v-shadow blur spread color* inset; 注释: box-shadow向框添加一个或多个阴影. 该属性是由逗号分隔的阴影列表,每个阴影由2-4个长度值、可选的颜色值及可选的inset关键词来规定。省略长度的值是0。 外阴影 a、给元素右边框和下边框加外阴影——把…...
文件夹删不掉,显示在另一个文件中打开怎么办
问题: 一、想要删掉这个文件夹,却因为文件夹中的文件打开了删不掉,这里我因为做的测试,所以是知道打开了什么 二、一般情况下文件比较多时,是不知道打开了什么的,长这个样子 解决: 一、打开任…...
阿里云香港云服务器租用_BGP多线网络_CN2高速线路测试
阿里云香港服务器中国香港数据中心网络线路类型BGP多线精品,中国电信CN2高速网络高质量、大规格BGP带宽,运营商精品公网直连中国内地,时延更低,优化海外回中国内地流量的公网线路,可以提高国际业务访问质量。阿里云服务…...
C# 异步方法的使用场景
我一直认为C#的异步方法只是一堆华而不实的东西,坑特别多,比起直接自建线程也没有任何优势。 直到有一天,一个需求场景,让我再次想到了C#的异步方法。 需求场景如下:需要写一个程序控制机械臂完成各种动作。每个动作要…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
