代码随想录算法训练营第三十三天丨 贪心算法part04

news2024/9/22 13:42:06

860.柠檬水找零

思路

这道题目刚一看,可能会有点懵,这要怎么找零才能保证完成全部账单的找零呢?

但仔细一琢磨就会发现,可供我们做判断的空间非常少!

只需要维护三种金额的数量,5,10和20。

有如下三种情况:

  • 情况一:账单是5,直接收下。
  • 情况二:账单是10,消耗一个5,增加一个10
  • 情况三:账单是20,优先消耗一个10和一个5,如果不够,再消耗三个5

此时大家就发现 情况一,情况二,都是固定策略,都不用我们来做分析了,而唯一不确定的其实在情况三。

而情况三逻辑也不复杂甚至感觉纯模拟就可以了,其实情况三这里是有贪心的。

账单是20的情况,为什么要优先消耗一个10和一个5呢?

因为美元10只能给账单20找零,而美元5可以给账单10和账单20找零,美元5更万能!

所以局部最优:遇到账单20,优先消耗美元10,完成本次找零。全局最优:完成全部账单的找零。

class Solution {
    public boolean lemonadeChange(int[] bills) {
        int five = 0;
        int ten = 0;
        for (int i = 0; i < bills.length; i++) {
            int bill = bills[i];
            if (bill == 5) {
                five++;
            }
            if (bill == 10) {
                five--;
                ten++;
            }
            if (bill == 20) {
                if (ten > 0) {
                    five--;
                    ten--;
                } else {
                    five -= 3;
                }
            }
            if (five<0||ten<0){
                return false;
            }
        }
        return true;
    }
}

406.根据身高重建队列

思路

本题有两个维度,h和k,看到这种题目一定要想如何确定一个维度,然后再按照另一个维度重新排列。

在135. 分发糖果 (opens new window)卡哥强调过一次,遇到两个维度权衡的时候,一定要先确定一个维度,再确定另一个维度。

如果两个维度一起考虑一定会顾此失彼

对于本题困惑的点是先确定k还是先确定h呢,也就是究竟先按h排序呢,还是先按照k排序呢?

如果按照k来从小到大排序,排完之后,会发现k的排列并不符合条件,身高也不符合条件,两个维度哪一个都没确定下来。

那么按照身高h来排序呢,身高一定是从大到小排(身高相同的话则k小的站前面),让高个子在前面。

此时我们可以确定一个维度了,就是身高,前面的节点一定都比本节点高!

那么只需要按照 k 为下标重新插入队列就可以了,为什么呢?

以图中{5,2} 为例:

406.根据身高重建队列

按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。

所以在按照身高从大到小排序后:

局部最优:优先按身高高的people的k来插入。插入操作过后的people满足队列属性

全局最优:最后都做完插入操作,整个队列满足题目队列属性

局部最优可推出全局最优,找不出反例,那就试试贪心。

怎么知道局部最优就可以推出全局最优呢? 有数学证明么?

在贪心系列开篇词关于贪心算法,你该了解这些! (opens new window)中,卡哥已经讲过了这个问题了。

刷题或者面试的时候,手动模拟一下感觉可以局部最优推出整体最优,而且想不到反例,那么就试一试贪心,至于严格的数学证明,就不在讨论范围内了。

如果没有读过关于贪心算法,你该了解这些! (opens new window)建议读一下,相信对贪心就有初步的了解了。

回归本题,整个插入过程如下:

排序完的people: [[7,0], [7,1], [6,1], [5,0], [5,2],[4,4]]

插入的过程:

  • 插入[7,0]:[[7,0]]
  • 插入[7,1]:[[7,0],[7,1]]
  • 插入[6,1]:[[7,0],[6,1],[7,1]]
  • 插入[5,0]:[[5,0],[7,0],[6,1],[7,1]]
  • 插入[5,2]:[[5,0],[7,0],[5,2],[6,1],[7,1]]
  • 插入[4,4]:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]

此时就按照题目的要求完成了重新排列。

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        // 身高从大到小排(身高相同k小的站前面)
        Arrays.sort(people, (a, b) -> {
            if (a[0] == b[0]) return a[1] - b[1];   // a - b 是升序排列,故在a[0] == b[0]的狀況下,会根据k值升序排列
            return b[0] - a[0];   //b - a 是降序排列,在a[0] != b[0],的状况会根据h值降序排列
        });
        LinkedList<int[]> queue = new LinkedList<>();

        for (int[] person : people) {
            //Linkedlist.add(index, value),会将value插入到指定index里。
            queue.add(person[1],person);
        }
        return queue.toArray(new int[people.length][]);
    }
}

452. 用最少数量的箭引爆气球

思路

如何使用最少的弓箭呢?

直觉上来看,貌似只射重叠最多的气球,用的弓箭一定最少,那么有没有当前重叠了三个气球,我射两个,留下一个和后面的一起射这样弓箭用的更少的情况呢?

尝试一下举反例,发现没有这种情况。

那么就试一试贪心吧!局部最优:当气球出现重叠,一起射,所用弓箭最少。全局最优:把所有气球射爆所用弓箭最少。

算法确定下来了,那么如何模拟气球射爆的过程呢?是在数组中移除元素还是做标记呢?

如果真实的模拟射气球的过程,应该射一个,气球数组就remove一个元素,这样最直观,毕竟气球被射了。

但仔细思考一下就发现:如果把气球排序之后,从前到后遍历气球,被射过的气球仅仅跳过就行了,没有必要让气球数组remove气球,只要记录一下箭的数量就可以了。

以上为思考过程,已经确定下来使用贪心了,那么开始解题。

为了让气球尽可能的重叠,需要对数组进行排序

那么按照气球起始位置排序,还是按照气球终止位置排序呢?

其实都可以!只不过对应的遍历顺序不同,我就按照气球的起始位置排序了。

既然按照起始位置排序,那么就从前向后遍历气球数组,靠左尽可能让气球重复。

从前向后遍历遇到重叠的气球了怎么办?

如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭

以题目示例: [[10,16],[2,8],[1,6],[7,12]]为例,如图:(方便起见,已经排序)

452.用最少数量的箭引爆气球

可以看出首先第一组重叠气球,一定是需要一个箭,气球3,的左边界大于了 第一组重叠气球的最小右边界,所以再需要一支箭来射气球3了。

代码如下:

class Solution {
    public int findMinArrowShots(int[][] points) {
        //怎么判断是否有重叠
        // 根据气球直径的开始坐标从小到大排序
        // 使用Integer内置比较方法,不会溢出
        Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
        // points 不为空至少需要一支箭
        int res = 1;
        for (int i = 1; i < points.length; i++) {
            // 气球i和气球i-1不挨着,注意这里不是>=
            if (points[i][0] > points[i-1][1]){
                res++;
            }else {//此时的情况为当前气球的左边界与前一气球有重叠
                points[i][1] = Math.min(points[i][1],points[i-1][1]); // 更新重叠气球最小右边界
            }
        }
        return res;
    }
}

自己有点思路,但是写不出来,还是得看卡哥的视频然后模仿着写,难受啊难受

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

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

相关文章

计算机中了mallox勒索病毒怎么办,勒索病毒解密,数据恢复

最近一段时间&#xff0c;云天数据恢复中心陆续收到很多企业的求助&#xff0c;企业的计算机服务器遭到了mallox勒索病毒攻击&#xff0c;导致企业的数据库无法正常使用&#xff0c;严重影响了企业的正常生产生活&#xff0c;为此&#xff0c;云天数据恢复中心的工程师通过对此…

【深度学习】使用Pytorch实现的用于时间序列预测的各种深度学习模型类

深度学习模型类 简介按滑动时间窗口切割数据集模型类CNNGRULSTMMLPRNNTCNTransformer 简介 本文所定义模型类的输入数据的形状shape统一为 [batch_size, time_step&#xff0c;n_features]&#xff0c;batch_size为批次大小&#xff0c;time_step为时间步长&#xff0c;n_feat…

Promise及相关知识细学

学习关键语句: Promise promise学习 promise.all promise.race promise.resolve 1. 写在前面 promise 是前端绕不开的东西 , 所以我们一定要好好学习 , 写这篇文章的目的是加深对 promise 的学习和使用程度 2. 开始 2.1 准备 首先创建一个文件夹 , 里面新建一个 index.htm…

Navicat 16 支持 Redis Cluster 集群模式 | 新功能 √

Redis Cluster 适用于需要处理大量数据和高并发访问&#xff0c;并且需要保证高可用性和可扩展性的场景。它在国内许多行业中都得到了广泛的应用。为了满足广大专业用户的需求&#xff0c;Navicat 16 再次升级&#xff0c;新增 Redis Cluster 功能&#xff0c;为Redis 用户带来…

FreeRTOS 计数型信号量 详解

目录 什么是计数型信号量&#xff1f; 计数型信号量相关 API 函数 1. 创建计数型信号量 2. 释放二值信号量 3. 获取二值信号量 计数型信号量实操 什么是计数型信号量&#xff1f; 计数型信号量相当于队列长度大于1 的队列&#xff0c;因此计数型信号量能够容纳多个资源&a…

探索JavaScript ES6+新特性

JavaScript是一门十分流行的编程语言&#xff0c;它不断发展演变以适应现代Web开发需求。ES6&#xff08;也称为ECMAScript 2015&#xff09;是JavaScript的第六个版本&#xff0c;引入了许多令人兴奋的新特性和语法糖。本文将介绍一些ES6中最有趣和实用的特性。 箭头函数 箭…

【人脸检测 FPS 1000+】ubuntu下libfacedetection tensorrt部署

TensorRT系列之 Windows10下yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov7 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov6 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov5 tensorrt模型加速…

解决问题:Expected one result (or null) to be returned by selectOne(),but found: 2]

在做一次数据迁移后&#xff0c;系统登录失败&#xff0c;日志报错&#xff1a; 原因&#xff1a;在数据迁移账号时&#xff0c;用户账号有两个相同的账号&#xff0c;所以导致登录失败。

成功项目经理总结的20个项目管理经验

大家好&#xff0c;我是老原。 有人说&#xff1a;项目管理是变理想为现实&#xff0c;化抽象为具体的一门科学和艺术。 这是对项目管理的一种精辟总结。项目管理专业的方法和知识能教会我们如何快捷、科学、艺术地做事。 因为它除了交付项目&#xff0c;更能管理人生。 毕…

代码随想录 | Day56

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 今日学习目标一、算法题1.最长公共子序列2.不相交的线3.最大子数组和 今日心得学习及参考书籍 今日学习目标 最长公共子序列&#xff08;1143&#xff09; 不相交的…

数据结构与算法—栈

目录 一、栈的概念及结构 二、栈的实现 1、声明栈结构体 2、初始化 3、 销毁 4、 入栈&#xff08;压栈&#xff09; 5、出栈&#xff08;弹栈&#xff09; 6、栈的大小 OJ练习 完整版&#xff1a; Stack.h声明 Stack.c函数 test.c参考测试用例 一、栈的概念及结构…

CLIP系列:CLIP:沟通文本和图像的桥梁

CLIP沟通文本和图像的桥梁。 SOTA的视觉任务模型需要固定的监督数据对&#xff0c;比如-大象&#xff0c;-兔子。这种方式在特定数据集上能够拥有很好的性能&#xff0c;但是在其他未知类别上的性能就会急剧下降。这种监督形式限制了模型的通用性&#xff0c;因为需要额外的数据…

linux配置静态路由

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言硬件&操作系统一、静态路由是什么&#xff1f;二、开始配置1.netplan2.NetworkManager1.CLI2.Desktop 三、开始测试总结 前言 最近有一个需求&#xff0c;…

C++数据结构X篇_23_快速排序(最快、不稳定的排序)

文章参考十大经典排序算法-快速排序算法详解进行整理补充。快速排序是最快的排序方法。 排序思路&#xff1a;分治法-挖坑填数&#xff1a;大问题分解为各个小问题&#xff0c;对小问题求解&#xff0c;使得大问题得以解决 文章目录 1. 什么是快速排序1.1 概念1.2 算法原理1.3 …

淘宝商品链接获取淘宝商品评论数据(用 Python实现淘宝商品评论信息抓取)

在网页抓取方面&#xff0c;可以使用 Python、Java 等编程语言编写程序&#xff0c;通过模拟 HTTP 请求&#xff0c;获取淘宝多网站上的商品详情页面评论内容。在数据提取方面&#xff0c;可以使用正则表达式、XPath 等方式从 HTML 代码中提取出有用的信息。值得注意的是&#…

android10.0(Q)编译安卓内核(pixel 2)

下载内核源码 1.查看内核版本 首先需要看一下内核的版本&#xff0c;可以在手机中看到内核版本 2.下载该内核版本对应的源码 cd ~/mount/project/androidq git clone https://aosp.tuna.tsinghua.edu.cn/android/kernel/msm.git cd msm git checkout 4fecde07e68d执行结果如…

Python之作业(三)

Python之作业&#xff08;三&#xff09; 练习题 给出3个整数&#xff0c;使用if语句判断大小&#xff0c;并升序输出有一个列表lst [1,4,9,16,2,5,10,15],生成一个新列表&#xff0c;要求新列表元素是lst相邻2项的和随机生成100个产品ID&#xff0c;ID格式如下 顺序的数字6…

SD-WAN跨境网络专线|跨境访问无忧!让海外SaaS平台与视频会议更稳定轻松的解决方案

在现如今全球化的时代&#xff0c;企业都有布局全球或是有潜力的国家&#xff0c;在海外开分公司必不可少&#xff0c;那与海外合作伙伴进行沟通与合作已经成为企业的常态。但是&#xff0c;访问海外的SaaS平台和进行视频会议时&#xff0c;我们经常会遇到网络不稳定、速度慢的…

m1 安装 cocoapods

其实最终解决问题很简单&#xff0c;麻烦的是如果找到解决问题的答案。 网上的答案一大堆&#xff0c;但不一定适合你的电脑&#xff0c;就好像天下的女人到处有&#xff0c;但不一定都适合你&#xff0c;一定要亲自试验一下才知道结果。 前提条件&#xff1a; 命令行工具&am…

Dunham‘s sports EDI需求分析

Dunhams Sports&#xff0c;成立于1937年&#xff0c;是美国领先的运动用品零售商之一。公司总部位于密歇根州&#xff0c;致力于提供广泛的体育用品和户外装备。Dunhams Sports的使命是为顾客提供最优质的运动体验&#xff0c;他们以卓越的服务和品质&#xff0c;赢得了无数荣…