当前位置: 首页 > news >正文

贪心算法总结及其leetcode题目N道

1 我为什么要写这个总结

1.1 字节笔试题

小明在玩一场通关游戏,初始血量为1,关卡有怪兽或者有血包(正数就是血包可回血数,负数说明是怪兽的伤害值),当捡到血包时会加血量,碰到怪兽时会掉血,现在指定初始血量为x,关卡是一个数组,小明必须按照数组的顺序玩游戏,当碰到一个怪兽时,他可以选择将这个怪兽扔到数组末尾,小明可以无限次地将怪兽移到数组末尾,问小明最少移动几次就能存活,如果无论怎么移动都不能存活则返回-1, 假设关卡是这样的[-200,-300,400],则返回-1,假如是这样的[200,100,-250,-60,-70,100],则返回1,只需要把-250挪到尾部,

思路:当发现自己血量不足时,就从当前已经遍历过的所有关卡中,选择耗费血量最多的那个关卡并且放到最后一关,如果即使这样挪开了耗血量最大的一关自身血量还是为负,则直接返回-1,说明无法通关

2 总结

2.1 什么是局部最优?

贪心关注的是局部最优,这里当前最优(指当前遍历的所有元素中的最优解)也是局部最优的一种,而一般的最有解又涉及到数据的最值,而且随着元素的不断向右扩展,可能这个最优值是不断变化的,所以一般可以使用堆来动态维护它的最值

2.2 解贪心类题目的一些分类

分为相向双指针,同向双指针以及最值堆等类型

2.2.1 相向双指针和同向双指针的解题思路的区别

  • 相向双指针通常用于处理排序数组中的问题,比如找出两个数的和等于特定值(如LeetCode题目167. 两数之和 II - 输入有序数组),或者反转数组(如LeetCode题目344. 反转字符串)。对于这类问题,两个指针分别从数组的头部和尾部出发,根据指向元素的大小关系向中间移动,直到两个指针相遇。

  • 同向双指针通常用于处理数组或字符串中需要连续元素满足特定条件的问题,比如找出满足特定和的最小子数组(如LeetCode题目209. 长度最小的子数组),或者找出最长的满足特定条件的子串(如LeetCode题目424. 替换后的最长重复字符)。对于这类问题,一个指针(快指针)用于遍历数组或字符串,另一个指针(慢指针)用于维护满足条件的区间。

2.2.2 在LeetCode上,与同向双指针和贪心策略相关的题目有很多。举两个例子:

  • 题目 209. 长度最小的子数组: 在一个正整数数组中寻找长度最小的连续子数组,其和至少为特定值。解决这个问题的方法是维持一个滑动窗口,窗口的左右边界就是同向的双指针。右指针向右移动以增加子数组的和,当子数组的和达到或超过目标值时,尝试将左指针向右移动以减小子数组的长度。

  • 题目 424. 替换后的最长重复字符: 给定一个字符串和一个整数k,找出可以通过最多替换k个字符以得到的最长的重复字符子串。解决这个问题的方法同样是维持一个滑动窗口,窗口的左右边界就是同向的双指针。右指针向右移动以增加子串的长度,当子串中最多的字符数量加上k小于子串的长度时,左指针向右移动。

2.3 一部分需要预处理的题目

2.3.1 可能需要排序

  1. 分发饼干

2.3.2 可能需要hashMap统计字符最后一次出现的位置

  1. 划分字母区间

3 使用堆解决问题的贪心策略

3.1 leetcode1046. 最后一块石头的重量

3.2 leetcode 1642. 可以到达的最远建筑

leetcode 1642. 可以到达的最远建筑

标准答案:

   // 砖块优先,砖块数量不足时考虑将当前替代最小高度的梯子改用砖块替代public int furthestBuilding(int[] heights, int bricks, int ladders) {int n=heights.length;//大根堆PriorityQueue<Integer>pq=new PriorityQueue<>((o1,o2)->(o2-o1));int i;int sum=0;//表示当前需要的梯子数量int sum_bri=0;for(i=1;i<n;i++){int diff=heights[i]-heights[i-1];if(diff>0){pq.offer(diff);sum_bri+=diff;//砖块的数量之和if(sum_bri>bricks){sum_bri-=pq.poll();sum++;}if(sum>ladders){return i-1;}}}return n-1;}//每次先放梯子,当梯子数量不足时,将当前使用过的梯子中,替代阶梯数最少的梯子找出来用对应砖头替换,替换出来的梯子拿到当前使用public int furthestBuilding(int[] heights, int bricks, int ladders) {int n=heights.length;//int[]:PriorityQueue<Integer>pq=new PriorityQueue<>((o1,o2)->(o1-o2));int i;int sum=0;//表示当前需要的砖块数量for(i=1;i<n;i++){int diff=heights[i]-heights[i-1];if(diff>0){pq.offer(diff);if(pq.size()>ladders){sum+=pq.poll();}if(sum>bricks){return i-1;}}}return n-1;}```我的答案:(有几个特别长的case过不了)```java
public int furthestBuilding2(int[] heights, int bricks, int ladders) {int n=heights.length;PriorityQueue<Integer>pq=new PriorityQueue<>((o1,o2)->(o1-o2));int i;for(i=1;i<n;){int diff=heights[i-1]-heights[i];// System.out.println("i:"+i+",diff:"+diff+",heights[i-1]:"+heights[i-1]+",heights[i]:"+heights[i]);if(diff<0){int diffAbs=-diff;if(ladders>0){ladders--;pq.add(diffAbs);}else if(bricks>=diffAbs){bricks-=diffAbs;}else{int newd=Integer.MAX_VALUE;if(!pq.isEmpty()){newd=pq.peek();}if(bricks>=newd){pq.poll();bricks-=newd;ladders++;i=i-1;}else{break;}}}i++;}return i-1;}

这里还有一个二分查找的方法:
每太整明白:

3.3 121. 买卖股票的最佳时机(虽然使用堆的方法不是最优解,但是方便和其他题目对比得出最优解)

3.3.1 这个题和3.1以及3.2有什么异同呢?

同:都涉及到取最值,而且最值都是可能变化的
不同:3.1以及3.2中的题目一个最值只能使用一次,一旦使用就得poll操作,而本题中的最值可以复用。正式这个特性导致了前者只能使用堆来维护最值(因为可能需要多次取最值,即使用到多个最值,poll操作只能靠堆维护),虽说本题也多次最最值,但是可以重用最值,没有poll操作。

class Solution {// 使用堆维护最小值public int maxProfit(int[] prices) {int n=prices.length;//表示到第i天时,股票的历史最低点价格PriorityQueue<Integer>pq=new PriorityQueue<>((o1,o2)->(o1-o2));int max=0;for(int i=0;i<n;i++){pq.add(prices[i]);max=Math.max(max,prices[i]-pq.peek());}return max;}// 方法:使用dp维护已经遍历值得最小值public int maxProfit3(int[] prices) {int n=prices.length;//表示到第i天时,股票的历史最低点价格int[]f=new int[n];f[0]=prices[0];int max=0;for(int i=1;i<n;i++){f[i]=Math.min(f[i-1],prices[i]);max=Math.max(max,prices[i]-f[i]);}return max;}// 方法:使用一个变量维护已经遍历值得最小值public int maxProfit(int[] prices) {int n=prices.length;//表示到第i天时,股票的历史最低点价格int min=prices[0];int max=0;for(int i=1;i<n;i++){min=Math.min(min,prices[i]);max=Math.max(max,prices[i]-min);}return max;}// 使用单调栈维护已经遍历序列的最小值public int maxProfit2(int[] prices) {int n=prices.length;Deque<Integer>st=new ArrayDeque<>();int max=0;st.add(prices[0]);for(int i=1;i<n;i++){int p=prices[i];if(!st.isEmpty()&&p<=st.peekLast()){max=Math.max(st.peekLast()-st.peekFirst(),max);while(!st.isEmpty()&&st.peekLast()>=p){st.pollLast();}}st.addLast(p);}if(!st.isEmpty()){max=Math.max(st.peekLast()-st.peekFirst(),max);}return max;}
}

3.3 871题最低加油次数和

3.4 630课程表III

4 使用相向双指针解决问题的贪心策略

4.1 167. 两数之和 II - 输入有序数组

思路:双指针解决偏差

class Solution {public int[] twoSum(int[] numbers, int target) {int n=numbers.length;int i=0,j=n-1;while(i<j){int sum=numbers[i]+numbers[j];if(sum>target){j--;}else if(sum<target){i++;}else{return new int[]{i+1,j+1};}}return new int[]{i+1,j+1};}}

4.2 11. 盛最多水的容器

思路:容器能盛的水取决于短板,不断移动双指针中代表较小数值的那个指针,直到两个指针相遇,其中得到的所有可能的盛水量中取最大值即可。

class Solution {public int maxArea(int[] height) {int n=height.length;int i=0,j=n-1;int max=-1;while(i<j){int s=(j-i)*Math.min(height[i],height[j]);max=Math.max(max,s);if(height[i]>height[j]){j--;}else{i++;}}return max;}
}

5 同向双指针与贪心策略

5.1 763. 划分字母区间(找出数组中满足特定条件的子序列)

class Solution {public List<Integer> partitionLabels(String s) {int n=s.length();int[]mp=new int[26];for(int i=0;i<n;i++){mp[s.charAt(i)-'a']=i;}List<Integer>res=new ArrayList<>();int start=0,end=0;for(int i=0;i<n;i++){end=Math.max(end,mp[s.charAt(i)-'a']);if(end==i){res.add(i-start+1);start=i+1;}}return res;}
}

相关文章:

贪心算法总结及其leetcode题目N道

1 我为什么要写这个总结 1.1 字节笔试题 小明在玩一场通关游戏&#xff0c;初始血量为1&#xff0c;关卡有怪兽或者有血包&#xff08;正数就是血包可回血数&#xff0c;负数说明是怪兽的伤害值&#xff09;&#xff0c;当捡到血包时会加血量&#xff0c;碰到怪兽时会掉血&am…...

k8s的namespace一直处于terminating的解法

先试了强制替换&#xff0c;无法替换掉&#xff0c;强制删除&#xff0c;也删除不掉namespace [rootmaster k8s-study]# vi ns-demo.yaml [rootmaster k8s-study]# kubectl create -f ns-demo.yaml namespace/demo created [rootmaster k8s-study]# kubectl get -f ns-demo.ya…...

JAVA面试总结-Redis篇章(六)——数据过期策略

Java面试总结-Redis篇章&#xff08;六&#xff09;——数据过期策略 Redis数据删除策略——惰性删除Redis数据删除策略——定期删除 Redis数据删除策略——惰性删除 Redis数据删除策略——定期删除...

【LLM】大语言模型学习之LLAMA 2:Open Foundation and Fine-Tuned Chat Model

大语言模型学习之LLAMA 2:Open Foundation and Fine-Tuned Chat Model 快速了解预训练预训练模型评估微调有监督微调(SFT)人类反馈的强化学习(RLHF)RLHF结果局限性安全性预训练的安全性安全微调上手就干使用登记代码下载获取模型转换模型搭建Text-Generation-WebUI分发模型…...

Android是如何识别USB信号的

Android设备通过USB接口与外部设备通信时&#xff0c;会通过USB控制器&#xff08;USB Controller&#xff09;与USB设备进行通信。USB控制器是Android设备的一个硬件组件&#xff0c;它负责管理USB总线并控制所有USB设备的连接和通信。 当一个USB设备被插入Android设备的USB接…...

机器学习前言

1.机器学习和统计学关系 2.机器学习的发展 3.机器学习与深度学习的相同点与不同点 4.机器学习和深度学习优缺点 一、机器学习和统计学关系 机器学习和统计学密切相关&#xff0c;可以说机器学习是统计学在计算机科学和人工智能领域的应用。机器学习和统计学在方法论和技术上有…...

Java另一种debug方法(not remote jmv debug),类似python远程debug方式

这种Debug类似python的debug方式&#xff0c;是运行时将业务代码及依赖推送到Linux并使用Linux的java运行运行程。只要本地能运行&#xff0c;就能自动将代码推送到Linux运行&#xff0c;不需打包及设置远程debug jvm参数&#xff0c;适合一些项目Debug调试 运行时会推送一些依…...

【QT】Day4

1> 思维导图 2> 手动完成服务器的实现&#xff0c;并具体程序要注释清楚 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> //服务器类 #include <QTcpSocket> //客户端类 #include <QMessageBox> //…...

在CSDN学Golang云原生(Kubernetes Pod 有状态部署)

一&#xff0c;StatefulSet部署MongoDB集群 Kubernetes StatefulSet 是 Kubernetes 中的一种资源类型&#xff0c;它能够保证有状态服务&#xff08;Stateful Service&#xff09;的唯一性和顺序部署&#xff0c;适用于需要持久化存储、网络标识、状态管理等场景。MongoDB 是一…...

sql-从一个或多个表中向一个表中插入 多行

INSERT还可以将SELECT语句查询的结果插入到表中&#xff0c;此时不需要把每一条记录的值一个一个输入&#xff0c;只需 要使用一条INSERT语句和一条SELECT语句组成的组合语句即可快速地从一个或多个表中向一个表中插入 多行。 基本语法格式如下&#xff1a; INSERT INTO 目标表…...

ElementUI 实现动态表单数据校验(已解决)

文章目录 &#x1f34b;前言&#xff1a;&#x1f34d;正文1、探讨需求2、查阅相关文档&#xff08;[element官网](https://element.eleme.cn/#/zh-CN/component/form)&#xff09;官方动态增减表单项示例3、需求完美解决4、注意事项 &#x1f383;专栏分享&#xff1a; &#…...

Linux上定位线上CPU飙高

【模拟场景】 写一个java main函数&#xff0c;死循环打印 System.out.println(“111111”) &#xff0c; 将其打成jar包放在linux中执行 1、通过TOP命令找到CPU耗用最厉害的那个进程的PID 2、top -H -p 进程PID 找到进程下的所有线程 可以看到 pid 为 94384的线程耗用cpu …...

06-行向量列向量_向量的运算 加法,数乘,减法,转置

行向量和列向量 行向量是按行把向量排开&#xff08;横着来写&#xff09;&#xff0c; 列向量是按列把向量排开&#xff08;竖着来写&#xff09; 在数学中我们更多的把数据写成列向量&#xff0c;在编程语言中更多的把数据存成行向量! 如果想在编程语言中把行向量转化成列…...

基于Matlab实现最大类间方差阈值与遗传算法的道路分割(附上完整源码+图像+程序运行说明)

道路分割是计算机视觉和图像处理中的一个重要任务&#xff0c;它在交通监控、自动驾驶和地图制作等领域具有广泛的应用。其中&#xff0c;最大类间方差阈值和遗传算法是道路分割中常用的方法之一。本文将介绍如何使用Matlab实现最大类间方差阈值与遗传算法进行道路分割。 文章目…...

13.4.2 【Linux】sudo

相对于 su 需要了解新切换的使用者密码 &#xff08;常常是需要 root 的密码&#xff09;&#xff0c; sudo 的执行则仅需要自己的密码即可。sudo 可以让你以其他用户的身份执行指令 &#xff08;通常是使用 root 的身份来执行指令&#xff09;&#xff0c;因此并非所有人都能够…...

电脑软件:键盘按键修改器——keytweak使用介绍

对你的电脑键盘的布局不满意、键盘上的某个按键坏掉了等等键盘问题如何解决&#xff1f;有了KeyTweak这一切就可以轻松解决了&#xff0c;KeyTweak是一个免费软件程序&#xff0c;使用它可让你重新映射键盘键。如果您改变主意并想将其改回原样&#xff0c;只需点击一下即可容易…...

软件工程学术顶会——ICSE 2023 议题(网络安全方向)清单与摘要

按语&#xff1a;IEEE/ACM ICSE全称International Conference on Software Engineering&#xff0c;是软件工程领域公认的旗舰学术会议&#xff0c;中国计算机学会推荐的A类国际学术会议&#xff0c;Core Conference Ranking A*类会议&#xff0c;H5指数74&#xff0c;Impact s…...

【Python】jupyter Linux服务器使用

文章目录 环境使用访问 环境 pip install jupyter 使用 在你想访问的目录下执行&#xff1a; jupyter notebook --ip0.0.0.0jupyter 给出提示&#xff1a; [I 2023-07-28 14:32:43.589 ServerApp] Package notebook took 0.0000s to import [I 2023-07-28 14:32:43.597 Ser…...

element 级联 父传子

html代码例子 父组件 <el-cascaderstyle"width: 100%"change"unitIdChange":options"unitOptions"filterablev-model"formInline.unitId":props"unitProps"/></el-form-item>//改变级联传值到这个组件里面<r…...

【MTI 6.S081 Lab】Copy-on-write

【MTI 6.S081 Lab】Copy-on-write The problemThe solutionImplement copy-on-write fork (hard)实验任务Hints解决方案问题解决思考uvmcopykfreekallockpagerefcow_handlertrap 虚拟内存提供了一定程度的间接性&#xff1a;内核可以通过将PTE标记为无效或只读来拦截内存引用&a…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...