算法通过村第十七关-贪心|白银笔记|贪心高频问题

news2024/11/15 11:06:31

文章目录

  • 前言
  • 区间问题
    • 判断区间是否重复
    • 合并区间
    • 插入区间
  • 字符串分割
  • 加油站问题
  • 总结


前言


提示:如果生活把你的门关上了,那你就再打开,这就是门,门就是这样的。 --佚名

贪婪的思想不一定要理解的很透彻,但是贪婪的问题我们要掌握的很好,这里我们就研究一些高频的考察题目。

区间问题

区间问题就是典型的面试中常见到的,这类面试题还是很受欢迎的,容易考察应聘者到底会不会写好代码。我们看看一些区间的例子🌰.两个区间的所有可能关系如下所示:

对于所有区间的问题,我们还是看看下面的图,一定要记住这些关系,很常见,也很容易出。

在这里插入图片描述

判断区间是否重复

参考地址连接:【leetcode】252 会议室(数组)_给定一个会议时间安排的数组-CSDN博客

在这里插入图片描述
看下图🥰:
在这里插入图片描述
因为一个人同一时刻只能参加一个会议,因此题目实质是判断是否存在重叠区间的。将区间按照会议开始时间进行排序,然后遍历一遍判断后面的会议开始的时候是否前面的会议还没有结束即可,也就是上面的图中所显示的,如果存在重叠直接返回false即可。

    /**
     * 会议室(数组)
     *
     * @param intervals
     * @return
     */
    public static boolean canAttendMeetings(int[][] intervals) {
        //将区间排序
        Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);

        // 遍历所有会议,是否出现重复 ( 技巧 从1 开始
        for (int i = 1; i < intervals.length; i++) {
            if (intervals[i][0] < intervals[i - 1][1]) {
                return false;
            }
        }
        return true;
    }

合并区间

参考题目参数:56. 合并区间 - 力扣(LeetCode)

在这里插入图片描述
在这里插入图片描述
看下图🥰:
在这里插入图片描述
和上一题一样,首先对区间按照起点端点进行升序排序,然后逐个判断当前区间是否与前一个区间重叠,如果不重叠的话直接加入结果集,反之重叠的话(当前区间与前一个区间进行合并)

 /**
     * 合并区间
     * @param intervals
     * @return
     */
    public static int[][] merge(int[][] intervals) {
        // 排序数组
        Arrays.sort(intervals,(v1,v2) ->v1[0] - v2[0]);
        // 创建新的区间
        int[][] merge = new int[intervals.length][2];
        int idx = -1;
        // 遍历数组
        for(int [] interval: intervals){
            // 如果数组是空的或者当前区间的起始位置 > 结果数组中最后区间的最大值
            // 不合并区间,直接加入区间
            if (idx == -1 && interval[0] > merge[idx][1]){
                merge[++idx] = interval;
            }else{
                // 反之说明重叠,则将当前区间合并至结果数组的最后区间
                merge[idx][1] = Math.max(merge[idx][1],interval[1]);
            }
        }
        return Arrays.copyOf(merge, idx + 1);
    }

插入区间

参考题目地址:57. 插入区间 - 力扣(LeetCode)

在这里插入图片描述
本题目也是上一个题目的扩展,这里区间已经按照起始结束升序排列了,我们可以直接遍历区间,寻找新区间的插入位置就可以了。

  1. 首先经新新区间左边且相离的区间加入结果集(遍历时,如果当前区间的结束位置,小于新区见的开始位置,说明当前区间在新区间的左边且相离)。
  2. 接着判断当前区间是否与新区间重叠,重叠的话就进行合并,知道遍历到当前区间在新区间的右边且相离,将最终合并后的新区间加入结果集;
  3. 最后将结果集右边且相离的区间加入结果集。
    /**
     * 插入区间
     * @param intervals
     * @param newInterval
     * @return
     */
    public static int[][] insert(int[][] intervals, int[] newInterval) {
        // 创建一个足够大的数组
        int[][] res = new int[intervals.length + 1][2];
        int idx = 0;
        // 左边的先进入(intervals[i][1] < newInterval[0]
        //(后面还用的到
        int i = 0;
        while(i < intervals.length && intervals[i][1] < newInterval[0] ){
            res[++idx] = intervals[i++];
        }
        // 合并新区间
        while(i < intervals.length && intervals[i][0] <= newInterval[1]){
            // 最左端
            newInterval[0] = Math.min(newInterval[0], intervals[i][0]);
            // 最右端
            newInterval[1] = Math.min(newInterval[1],intervals[i][0]);
            i++;
        }
        // 将合并的区间放入结果集
        res[idx++]= newInterval;
        // 放入右边的,直接放入结果集
        while(i < intervals.length){
            res[idx++]= intervals[i++];
        }

        return Arrays.copyOf(res,idx);
    }

字符串分割

参考题目地址:763. Partition Labels - 力扣(LeetCode)

在这里插入图片描述

在这里插入图片描述
这个问题,有点回溯。分割问题是回溯算法的典型应用,但是这个问题如果用回溯将很复杂。题目要求同一个字母最多出现在一个片段中,那么要如何进行分片才算合理呢?🤔

该遍历过程相当于找每个字母的边界,如果知道之前遍历过的所有字母的最远边界,说明这个边界就是分割点了,此时前面出现的所有字母,最远也就到这个边界,所以做如下操作:

  • 首先,统计每一个字符最后出现的位置
  • 然后从头遍历字符,并更新字符的最远出现的下标,如果找到字符最远出现的下标和当前下标相等,则找到分割点。

在这里插入图片描述

直接上代码:这个太神了

   /**
     * 划分字母区间
     *
     * @param S
     * @return
     */
    public static List<Integer> partitionLabels(String S) {
        List<Integer> res = new ArrayList<Integer>();
        int[] edge = new int[26];
        char[] chars = S.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            // 只保留最后一次的位置
            edge[chars[i] - 'a'] = i;
        }
        int idx = 0;
        int last = -1;
        for (int i = 0; i < chars.length; i++) {
            idx = Math.max(idx, edge[chars[i] - 'a']);
            if (i == idx) {
                // 这个非常巧妙
                res.add(i - last);
                last = i;
            }
        }
        return res;
    }

加油站问题

参考题目介绍:134. 加油站 - 力扣(LeetCode)

在这里插入图片描述
在这里插入图片描述

我们说做贪婪的题目,如果不管什么是贪婪,就直接做题。这里解释以下题目的含义:

实例给我们了两个数组,知识代表了当前站提供的油料,以及从前一个站过来需要消耗多少油料,因为是环,所以这里gas[0] = 1 和gas[0] = 3 就表示第一个站有1升汽油,从第一个站到第二个站需要消耗3升汽油.

当然最简单的方式是暴力从第一个试到最后一个。如图:

在这里插入图片描述
我们一直向后找,可以的话是一定有答案的。

但是,这个问题需要大量的重复计算,优化以下:

  1. 首先,如果总的油量大于(等于)总的消耗量,那么是可以跑完一圈的,具体就每段我们要考虑以下了。在具体一点是各个站的剩余油量rest[i]相加一点是大于等于零的。
  2. 每个加油站的剩余量rest[i]为gas[i] - cost[i].从i到0开始累加rest[i],和基座curSum,一旦curSum小于零,说明[0,i]区间都不能做起始位置,起始位置必须从i + 1开始重新算,只有这样才能保证我们有可能完成。
    在这里插入图片描述
    代码展示:
  public int canCompleteCircuit(int[] gas, int[] cost) {
        int start = 0;
        int totalSum = 0;
        int curSum = 0;
        for(int i = 0; i < gas.length; i++){
            curSum += gas[i] - cost[i];
            totalSum += gas[i] - cost[i];
            if(curSum < 0){
                // 更新起始位置
                start = i + 1;
                // 更新curSum
                curSum = 0;
            }
        }
        // 说明不能走一圈
        if(totalSum < 0){
            return -1;
        }
        return start;
    }

总结

提示:区间问题;字符串分割;加油站;贪婪算法;区间划分


如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

如有不理解的地方,欢迎你在评论区给我留言,我都会逐一回复 ~

也欢迎你 关注我 ,喜欢交朋友,喜欢一起探讨问题。
在这里插入图片描述

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

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

相关文章

学习Java应该关注哪些网站?

前言 下面是我总结的一些不错的网站&#xff0c;可以收藏看一下哈~希望对你有帮助 一、入门教程类 主要是教程性质的网站&#xff0c;主要是新手学习参考以及相关知识的内容参考 1、菜鸟教程&#xff08;https://www.runoob.com&#xff09; 2、Java学习笔记&#xff08;http…

2023年【广东省安全员A证第四批(主要负责人)】考试内容及广东省安全员A证第四批(主要负责人)模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 广东省安全员A证第四批&#xff08;主要负责人&#xff09;考试内容根据新广东省安全员A证第四批&#xff08;主要负责人&#xff09;考试大纲要求&#xff0c;安全生产模拟考试一点通将广东省安全员A证第四批&#x…

红眼特效出处竟是斯大林电脑病毒

相信不少小伙伴看过这种红眼特效的视频&#xff0c;那么你知道这个特效最早出自哪里吗&#xff1f; 其实这个红眼病毒最早出于一个俄罗斯的电脑病毒斯大林上&#xff0c;一旦电脑感染这个病毒&#xff0c;屏幕上就会出现一个红眼特效的斯大林&#xff0c;同时不断播放前苏联国…

学习笔记:最小生成树

最小生成树 引入 我们定义无向连通图的 最小生成树&#xff08;Minimum Spanning Tree&#xff0c;MST&#xff09;为边权和最小的生成树。 注意&#xff1a;只有连通图才有生成树&#xff0c;而对于非连通图&#xff0c;只存在生成森林。 实现 求最小生成树的算法有 Prim…

力扣每日一题73:矩阵置零

题目描述&#xff1a; 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]示例 2…

多线程---wait和notify

文章目录 使用场景使用方法原理notify VS notifyAll 使用场景 我们都知道线程的调度是“随机的”&#xff0c;但是我们在很多时候都希望多个线程能够按照一个预期的顺序来执行。wait和notify就是用来调配线程执行顺序的。 使用方法 public static void main(String[] args) {…

Hand Avatar: Free-Pose Hand Animation and Rendering from Monocular Video

Github&#xff1a; https://seanchenxy.github.io/HandAvatarWeb 1、结构摘要 MANO-HD模型&#xff1a;作为高分辨率网络拓扑来拟合个性化手部形状将手部几何结构分解为每个骨骼的刚性部分&#xff0c;再重新组合成对的几何编码&#xff0c;得到一个跨部分的一致占用场纹理建…

?SW转cad尺寸不一致

应该是330 中心线不对

x86-32-Linux下栈溢出攻击原理

在x86-32-Linux下构造一个栈溢出攻击 栈缓冲区溢出攻击&#xff1a;向栈上的数组写入超过数组长度的数据导致覆盖到正常数据{栈帧上的返回地址}。 IA-32下C函数调用约定&#xff1a; 调用者将参数从右向左入栈&#xff0c;构造参数call 指令短跳转&#xff0c;会将call指令下一…

【每日一题】从数量最多的堆取走礼物

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;排序方法二&#xff1a;优先队列 其他语言python3 写在最后 Tag 【优先队列】【排序】【数组】【2023-10-28】 题目来源 2558. 从数量最多的堆取走礼物 ​ 题目解读 执行 k 次操作&#xff0c;每次从数量最多的堆中取…

VirtualBox 安装 麒麟Linux

为了验证Oracle EM是否可以管理麒麟OS和其上的Oracle数据库&#xff0c;今天试着在VirtualBox上装了麒麟Linux&#xff0c;也就是银河麒麟。整个过程比较顺畅。 选定ISO文件后&#xff0c;操作系统自动识别为Red Hat。勾选“跳过自动安装”&#xff1a; 内存和CPU选的默认值&…

AFsim 仿真运行

创建完仿真模型平台后&#xff0c;点击Warlock.exe程序&#xff0c;弹出仿真运行的窗口&#xff0c;点击浏览选择创建好的test文件&#xff0c;点击运行。 点击运行后&#xff0c;进入仿真运行的主页面&#xff0c;如下图所示&#xff1a; 1.仿真控制 顶部工具栏中文件的内容。…

【C++】mapset的底层结构 -- AVL树(高度平衡二叉搜索树)

前面我们对 map / multimap / set / multiset 进行了简单的介绍&#xff0c;可以发现&#xff0c;这几个容器有个共同点是&#xff1a;其底层都是按照二叉搜索树来实现的。 但是二叉搜索树有其自身的缺陷&#xff0c;假如往树中插入的元素有序或者接近有序&#xff0c;二叉搜索…

数据结构 | 算法的时间复杂度和空间复杂度【详解】

数据结构 | 算法的时间复杂度和空间复杂度【详解】 1. 什么是数据结构&#xff1f; 数据结构(Data Structure)是计算机存储、组织数据的方式&#xff0c;指相互之间存在一种或多种特定关系的数据元素的集合。 2. 什么是算法&#xff1f; 算法(Algorithm):就是定义良好的计算过…

C++前缀和算法的应用:预算内的最多机器人数目

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 单调双向队列 滑动窗口 题目 你有 n 个机器人&#xff0c;给你两个下标从 0 开始的整数数组 chargeTimes 和 runningCosts &#xff0c;两者长度都为 n 。第 i 个机器…

Maven - no main manifest attribute(SpringBoot 多模块)

问题描述 no main manifest attribute 解决方案 一个主项目下&#xff0c;多个业务模块&#xff0c;假设 starter 模块作为启动器&#xff0c;以及主项目&#xff08;project&#xff09;最外层父 pom.xml 最关键要关注这 2 个 pom.xml&#xff08;starter - pom.xml & p…

python画气泡标尺图

目录 渐变气泡图彩色气泡图 在进行实验结果分析的时候&#xff0c;气泡标尺图能非常清晰对不同的结果进行多维度的比较&#xff0c;特别是在深度学习模型大小和精度进行比较的时候非常合适使用&#xff0c;以下是几个例子。 渐变气泡图 import seaborn as sns import matplotl…

正点原子嵌入式linux驱动开发——Linux 串口RS232/485/GPS 驱动

串口是很常用的一个外设&#xff0c;在Linux下通常通过串口和其他设备或传感器进行通信&#xff0c;根据 电平的不同&#xff0c;串口分为TTL和RS232。不管是什么样的接口电平&#xff0c;其驱动程序都是一样的&#xff0c;通过外接RS485这样的芯片就可以将串口转换为RS485信号…

RZMO-A-030/210、HZMO-A-030/315电控比例压力阀控制器

RZMO-A-030/50、RZMO-A-030/210、RZMO-A-030/350、RZMO-A-030/100、RZMO-A-030/315、HZMO-A-030/50、HZMO-A-030/210、HZMO-A-030/350、HZMO-A-030/100、HZMO-A-030/315滑阀型先导式数字型比例溢流阀&#xff0c;用于压力开环控制&#xff0c;可提供板式或叠加式安装。A型&…

web - 前段三剑客

目录 前言 一. HTML 常用标签演示 图片标签 ​编辑 表格标签(重点) ​编辑 表单标签 (重点) 布局标签 其余标签 二. CSS 2.1 . css的三种引入方式 2.2 . 三大选择器 2.3 . css样式 - 浮动 2.4 . css样式 - 定位 1.static 2.absolute(绝对位置) 3.relavite(相…