day34 贪心算法 455.分发饼干 376. 摆动序列

news2024/11/25 11:05:18

贪心算法理论基础

贪心的本质是选择每一阶段的局部最优,从而达到全局最优

贪心一般解题步骤(贪心无套路):

  • 将问题分解为若干个子问题
  • 找出适合的贪心策略
  • 求解每一个子问题的最优解
  • 将局部最优解堆叠成全局最优解

455.分发饼干

这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩

或者是

局部最优就是小饼干喂给胃口小的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩

注意事项:注意两种情况

//大饼干满足胃口大的孩子 (最大饼干一定要用所以for控制胃口)

代码中先遍历的胃口,在遍历的饼干,那么可不可以 先遍历 饼干,在遍历胃口呢?其实是不可以的。外面的 for 是里的下标 i 是固定移动的,而 if 里面的下标 index 是符合条件才移动的。

如果 for 控制的是饼干, if 控制胃口,就是出现如下情况 :、

if 里的 index 指向 胃口 10, for 里的 i 指向饼干 9,因为 饼干 9 满足不了 胃口 10,所以 i 持续向前移动,而 index 走不到s[index] >= g[i] 的逻辑,所以 index 不会移动,那么当 i 持续向前移动,最后所有的饼干都匹配不上。        所以 一定要 for 控制 胃口,里面的 if 控制饼干。

//小饼干满足胃口小的孩子   for控制饼干  if控制胃口(最小胃口一定要被喂所以for控制饼干)

//大饼干满足胃口大的孩子
class Solution {

    public int findContentChildren(int[] g, int[] s) {
		Arrays.sort(g);
		Arrays.sort(s);
		int index = s.length - 1;
		int result = 0 ;
		for (int i = g.length -1; i >=0; i--) {
            if(index >=0 && s[index] >= g[i]){
				 index--;
				 result++;
			 }
		}
		return result;
    }
}


//小饼干满足胃口小的孩子
class Solution {

    public int findContentChildren(int[] g, int[] s) {
		Arrays.sort(g);
		Arrays.sort(s);
		int index = 0;
		for (int i = 0; i < s.length; i++) {
            if(index < g.length && g[index] <= s[i]){
				 index++;
			 }
		}
		return index;
    }
}

误区

如果说使用这种代码的话,使用while判断可能会导致重复技术即g[1,2,3]  s[1,1]会导致结果为2而不是正确的情况只满足一个孩子,所以判断使用if。

for (int i = g.length -1; i >=0; i--) {
          while(index >=0 && s[index] >= g[i]){
       index--;
       result++;
    }
}

376. 摆动序列

局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值

整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列

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

大体思路:

在计算是否有峰值的时候,遍历下标 i ,计算 prediff(nums[i] - nums[i-1]) curdiff(nums[i+1] - nums[i]),如果prediff < 0 && curdiff > 0 或者 prediff > 0 && curdiff < 0 此时就有波动就需要统计。

三种情况:

  1. 情况一:上下坡中有平坡
  2. 情况二:数组首尾两端
  3. 情况三:单调坡中有平坡

上下坡中有平坡

在图中,当 i 指向第一个 2 的时候,prediff > 0 && curdiff = 0 ,当 i 指向最后一个 2 的时候 prediff = 0 && curdiff < 0

如果我们采用,删左面三个 2 的规则,那么 当 prediff = 0 && curdiff < 0 也要记录一个峰值,因为他是把之前相同的元素都删掉留下的峰值。

所以我们记录峰值的条件应该是: (preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0),为什么这里允许 prediff == 0 ,就是为了 上面我说的这种情况。

情况二:数组首尾两端(prediff=0为了解决数组最左端  最右端初始化为0)

如果只有两个不同的元素,那摆动序列也是 2。

可以假设,数组最前面还有一个数字,针对序列[2,5],可以假设为[2,2,5],这样它就有坡度了即 preDiff = 0,如图:

针对以上情形,result 初始为 1(默认最右面有一个峰值)

情况三:单调坡度有平坡(解决情况2出现的问题在坡度有变化时再prediff = curdiff)

我们忽略了一种情况,即 如果在一个单调坡度上有平坡,例如[1,2,2,2,3,4],如图:

在三个地方记录峰值,但其实结果因为是 2,因为 单调中的平坡 不能算峰值(即摆动)。

那么我们应该什么时候更新 prediff 呢?

我们只需要在 这个坡度 摆动变化的时候,更新 prediff 就行,这样 prediff 在 单调区间有平坡的时候 就不会发生变化,造成我们的误判。

总结:

本题异常情况的本质,就是要考虑平坡, 平坡分两种,一个是 上下中间有平坡,一个是单调有平坡,如图:

class Solution {
    public int wiggleMaxLength(int[] nums) {
         if(nums.length <=1)return nums.length;

		 int prediff = 0;
		 int curdiff =0;
		 int count = 1;
		for (int i = 1; i < nums.length; i++) {
			curdiff = nums[i] - nums[i-1];
			if ((curdiff > 0 && prediff <= 0) || (curdiff < 0 && prediff >= 0)) {
				count++;
				prediff = curdiff;  //在坡度变化时改变prediff
			}
			//prediff = curdiff; 这种写法解决不了单调有平坡的问题
		}
		//System.out.println(count);
		return count;
    }
}

53. 最大子序和

局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。

全局最优:选取最大“连续和”

常见误区

误区一:

不少同学认为 如果输入用例都是-1,或者 都是负数,这个贪心算法跑出来的结果是 0, 这是又一次证明脑洞模拟不靠谱的经典案例,建议大家把代码运行一下试一试,就知道了,也会理解 为什么 result 要初始化为最小负数了。

误区二:

大家在使用贪心算法求解本题,经常陷入的误区,就是分不清,是遇到 负数就选择起始位置,还是连续和为负选择起始位置。

在动画演示用,大家可以发现, 4,遇到 -1 的时候,我们依然累加了,为什么呢?

因为和为 3,只要连续和还是正数就会 对后面的元素 起到增大总和的作用。 所以只要连续和为正数我们就保留。

这里也会有录友疑惑,那 4 + -1 之后 不就变小了吗? 会不会错过 4 成为最大连续和的可能性?

其实并不会,因为还有一个变量 result 一直在更新 最大的连续和,只要有更大的连续和出现,result 就更新了,那么 result 已经把 4 更新了,后面 连续和变成 3,也不会对最后结果有影响

class Solution {
    public int maxSubArray(int[] nums) {
		if(nums.length == 1)return nums[0];

		int sum = Integer.MIN_VALUE;   //存储最大值
		int count = 0;    //统计大小
		for (int i = 0; i < nums.length; i++) {
			count += nums[i];
			sum = Math.max(sum,count);
			if(count <= 0) {
				count = 0;
			}

		}
 		return  sum;
    }
}

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

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

相关文章

go routing 之 gorilla/mux

1. 背景 继续学习 go 2. 关于 routing 的学习 上一篇 go 用的库是&#xff1a;net/http &#xff0c;这次我们使用官方的库 github.com/gorilla/mux 来实现 routing。 3. demo示例 package mainimport ("fmt""net/http""github.com/gorilla/mux&…

Python知识详解【1】~{正则表达式}

正则表达式是一种用于匹配字符串模式的文本工具&#xff0c;它由一系列普通字符和特殊字符组成&#xff0c;可以非常灵活地描述和处理字符串。以下是正则表达式的一些基本组成部分及其功能&#xff1a; 普通字符&#xff1a;大多数字母和数字在正则表达式中表示它们自己。例如…

深度学习之基于MTCNN+Facenet的人脸识别身份认证系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 随着信息技术的快速发展&#xff0c;身份认证技术在日常生活和工作中的重要性日益凸显。传统的…

初始MyBatis ,详细步骤运行第一个MyBatis程序,同时对应步骤MyBatis底层剖析

1. 初始MyBatis &#xff0c;详细步骤运行第一个MyBatis程序&#xff0c;同时对应步骤MyBatis底层剖析 文章目录 1. 初始MyBatis &#xff0c;详细步骤运行第一个MyBatis程序&#xff0c;同时对应步骤MyBatis底层剖析每博一文案2. 前沿知识2.1 框架&#xff08;framework&#…

Oracle递归查询笔记

目录 一、创建表结构和插入数据 二、查询所有子节点 三、查询所有父节点 四、查询指定节点的根节点 五、查询指定节点的递归路径 六、递归子类 七、递归父类 一、创建表结构和插入数据 CREATE TABLE "REGION" ( "ID" VARCHAR2(36) DEFAULT SYS_GUI…

jdk17安装教程详细(jdk17安装超详细图文)

2021年9月14日JDK17 发布&#xff0c;其中不仅包含很多新语言功能&#xff0c;而且与旧版 JDK 相比&#xff0c;性能提升也非常明显。与之前 LTS 版本的 JDK 8 和 JDK 11 相比&#xff0c;JDK17 的性能提升尤为明显&#xff0c;本文将教你如何安装 相比于JDK1.8&#xff0c;JD…

信号:MSK调制和GMSK调制

目录 一、MSK信号 1. MSK信号的第k个码元 2.MSK信号的频率间隔 3.MSK信号的相位连续性 3.1 相位路径 3.2初始相位ψk 4.MSK信号的产生 原理框图 5.MSK信号的频谱图 二、高斯最小频移键控(GMSK) 1.频率响应 2.GMSK调制产生方式 2.1 高斯滤波器法 2.2 正交调制器法…

《MySQL怎样运行的》—InnoDB数据页结构

在上一篇文章中我们讲了&#xff0c;InnoDB的数据页是InnoDB管理存储空间的基本单位&#xff0c;一个页的大小基本为16kb 那你有没有疑问&#xff0c;就是说这个InnoDB的数据页的结构是什么样的&#xff0c;还有他这些结构分别有那些功能~接下来我们一一讲解 数据页的总览结构…

内部类知识点

什么是内部类&#xff1f; 内部类何时出现&#xff1f;B类是A类的一部分&#xff0c;且B单独存在无意义 内部类分类 成员内部类&#xff1a; 当内部类被private修饰后&#xff0c;不能用方法2 调用外部类成员变量 内部类里面有隐藏的outer this来记录 静态内部类 创建对象&…

路由引入实验(华为)

思科设备参考&#xff1a;路由引入实验&#xff08;思科&#xff09; 技术简介 路由引入技术在网络通信中起着重要的作用&#xff0c;能够实现不同路由协议之间的路由传递&#xff0c;并在路由引入时部署路由控制&#xff0c;实现路径或策略的控制 实验目的 不同的路由协议之…

用Intellij实现web登录页面时,servlet已经配置好了,但是还是报404

今天看到一个404问题&#xff1a; 用Intellij实现web登录页面时&#xff0c;代码如下图所示。点击运行后会跳转到浏览器&#xff0c;但是输入/login时&#xff0c;浏览器显示404&#xff0c;且无法在控制面板上打印内容&#xff1b;输入/index时&#xff0c;也无法在浏览器上显…

html+css 驾考首页设计

效果 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>17sucai - A Pen by Mark Boots</title><!-- <link rel"stylesheet" href"./style.css"> --></head>…

【源码分享】简单的404 HTML页面示例,该页面在加载时会等待2秒钟,然后自动重定向到首页

展示效果 源码 html <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><title>404 页面未找到</title><meta http-equiv"refresh" content"2;url/"> <!-- 设置2秒后跳转到首…

[安洵杯 2019]crackMe

直接就退出程序了 找到关键函数了&#xff0c;好像用到了 hook 还有一个 嘿嘿&#xff0c;看着就是像 base64 只是 补‘’改成了‘ &#xff01; ’ 交叉引用啊&#xff0c;翻到一个应该是最后比较函数 1UTAOIkpyOSWGv/mOYFY4R!! 那一坨对 a1数组的操作没看懂 先总结一下就是…

Golang的基本使用

目录 变量的声明 Golang常用容器 defer 有趣的多态 结构体标签和reflect 反射 Golang最强的协程 channel go可能造成的内存泄露 变量的声明 方法 1:有类型,有var,不赋值 在Golang中默认值为0 方法 2:无类型,有var,赋值 方法 3:无类型,无var,赋值 多变量声明 多变…

C语言 数组——查找算法的函数实现

目录 线性查找&#xff08;Linear Search&#xff09; 线性查找的性能 猜数游戏 二分查找&#xff08;Binary Search&#xff09; 并非吹毛求疵&#xff0c;鸡蛋里挑骨头 二分查找的性能 线性查找&#xff08;Linear Search&#xff09; 不 要求数据表是已排好序的  …

AI巨头争相与Reddit合作:为何一个古老的论坛成为AI训练的“宝藏”?

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

这种电脑原来这么耗电……震惊了粉丝小姐姐

前言 在今年1月份的时候&#xff0c;一位来自重庆的小姐姐加了小白&#xff0c;咨询电脑的问题&#xff1a; 哦豁&#xff0c;这个电脑看着确实闪闪发光&#xff0c;是真的很漂亮&#xff5e;&#xff08;嗯&#xff0c;小姐姐也很漂亮&#xff09; 电脑无法开机&#xff0c;按…

华为云发布ServiceStage:内置优秀业界实践「云应用管理和运维」模板

迅猛发展的业务让企业IT系统架构愈加复杂&#xff0c;为满足业务快速迭代的需求&#xff0c;重点企业完成从传统单体应用架构到分布式微服务架构的升级。微服务架构虽可提升研发效率&#xff0c;但数量庞大的微服务实例间错综复杂的依赖关系无疑增加了部署运维难度。 同时&…