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

二分思想与相关问题(下)

接下来详细讲解几道比较难的例题,仔细体会二分和其他概念混合在一起的趣味。

下面这道题涉及了“碎片拼接”的概念,很妙,也很难想。

P r o b l e m 5 Problem5 Problem5 同时运行N台电脑的最长时间 LeetCode2141

你有 n 台电脑。给你整数 n 和一个下标从 0 开始的整数数组 batteries ,其中第 i 个电池可以让一台电脑 运行 batteries[i] 分钟。你想使用这些电池让 全部 n 台电脑 同时 运行。

一开始,你可以给每台电脑连接 至多一个电池 。然后在任意整数时刻,你都可以将一台电脑与它的电池断开连接,并连接另一个电池,你可以进行这个操作 任意次 。新连接的电池可以是一个全新的电池,也可以是别的电脑用过的电池。断开连接和连接新的电池不会花费任何时间。

注意,你不能给电池充电。

请你返回你可以让 n 台电脑同时运行的 最长 分钟数。

示例 1:

输入:n = 2, batteries = [3,3,3]
输出:4
解释:
一开始,将第一台电脑与电池 0 连接,第二台电脑与电池 1 连接。
2 分钟后,将第二台电脑与电池 1 断开连接,并连接电池 2 。注意,电池 0 还可以供电 1 分钟。
在第 3 分钟结尾,你需要将第一台电脑与电池 0 断开连接,然后连接电池 1 。
在第 4 分钟结尾,电池 1 也被耗尽,第一台电脑无法继续运行。
我们最多能同时让两台电脑同时运行 4 分钟,所以我们返回 4 。

示例 2:

输入:n = 2, batteries = [1,1,1,1]
输出:2
解释:
一开始,将第一台电脑与电池 0 连接,第二台电脑与电池 2 连接。
一分钟后,电池 0 和电池 2 同时耗尽,所以你需要将它们断开连接,并将电池 1 和第一台电脑连接,电池 3 和第二台电脑连接。
1 分钟后,电池 1 和电池 3 也耗尽了,所以两台电脑都无法继续运行。
我们最多能让两台电脑同时运行 2 分钟,所以我们返回 2 。

提示:

  • 1 <= n <= batteries.length <= 10^5
  • 1 <= batteries[i] <= 10^9

问题分析:

假设 N N N台电脑同时运行的时间的 t i m e time time,我们贪心地想,这个 t i m e time time越大,说明每台机器的耗电量越大,而电池的个数以及各自电量就那么点,就更容易把这些电池消耗完。也就是说,假设 N N N台电脑能够同时运行 t i m e time time时间,那么 N N N台电脑也一定能同时运行 t i m e − 1 time-1 time1时间,反之则不一定同时运行 t i m e + 1 time+1 time+1时间。

所以我们可以得出 t i m e time time N N N台电脑能否同时运行 t i m e time time时间具体单调函数关系:

现在我们来讨论怎么解决

​ 【问题5-1】给定整数 t i m e time time,返回 N N N台电脑能否同时运行 t i m e time time时间。

解决这个问题我们就要对电池的电量数组进行分析,如果某个电池的电量 e n e r g y > = t i m e energy >= time energy>=time,说明这个电池可以从0时刻开始就给某台电脑供电,直到 t i m e time time结束。我们称这种电池为”完美电池“,与之相对应的自然是碎片电池,碎片电池的电量 e n e r g y < t i m e energy < time energy<time。在整个分析过程中,我们可以把”完美电池单拎出来“,因为一个”完美电池“就可以完成一台电脑的供电,假设完美电池的个数为 m m m,那我们就只需要分析,在碎片电池组成的碎片电量数组条件下, N − m N-m Nm台电脑能否同时运行 t i m e time time时间。

这就涉及到**”碎片拼接“**问题了,我先给出结论:

​ 【结论5-1】只要碎片数组的累加和 s u m > = t i m e ∗ ( N − m ) sum >= time*(N-m) sum>=time(Nm),那么这N-m台电脑就可以同时运行time时间。

我们拿电量数组 [ 7 , 6 , 5 , 7 , 8 , 9 ] [7,6,5,7,8,9] [7,6,5,7,8,9](对应着 A , B , C , D , E , F A,B,C,D,E,F A,B,C,D,E,F号电池)来给甲乙丙丁四台电脑供电同时运行 10 10 10分钟来举例子。

从甲开始,甲先用 A A A电池供 7 7 7分钟电,剩下三分钟由 B B B电池供,那我就用 B B B电池给乙供电,供3分钟以便留3分钟给甲,那乙还需要七分钟,我们用 C C C电池给乙供剩下来的七分钟里的5分钟,剩余2分钟换 D D D供,那丙我就用 D D D供五分钟,再用 E E E供五分钟,丁先用 E E E供一分钟,剩下九分钟全用 F F F供。文字描述有点冗杂,同学们看下面这张图吧。

在这里插入图片描述

“碎片拼接”的证明我稍后再讲,现在我们只需要再分析一下二分筛选条件,这道题目就可以解出来了。

t i m e time time非负,所以左边界 l e f t = 0 left = 0 left=0 N N N台电脑的最长运行时间数肯定小于各电池的电量和 s u m sum sum,所以右边界 l e f t = s u m left = sum left=sum。如果这 N N N台机器不能同时运行 m i d mid mid时间,则选取左半部分作为收敛区间 r i g h t = m i d − 1 right = mid -1 right=mid1,如果这 N N N台机器可以同时运行 m i d mid mid时间,则选取右半部分作为收敛区间,并用 a n s w e r answer answer记录当前可行解 a n s w e r = m i d , l e f t = m i d + 1 answer = mid,left = mid+1 answer=mid,left=mid+1

解决代码:
bool check(vector<int>& batteries, long time, int n) {long sum = 0;for (int i : batteries) {if (i >= time) { // 完美電池n--;if (n == 0)return true;} else {sum += i;}if (sum >= time * n)return true;}return false;
}long long maxRunTime(int n, vector<int>& batteries) {long left = 0;long All = 0;for (int i : batteries) {All += i;}long right = All;long long answer = 0;while (left <= right) {long mid = left + ((right - left) >> 1);if (check(batteries, mid, n)) {answer = mid;left = mid + 1;} else {right = mid - 1;}}return answer;
}

这个解法其实还可以利用贪心分析进行优化,同学们可以自己思考思考。

P r o b l e m 6 Problem6 Problem6 计算等位时间

描述:

给定一个数组 a r r arr arr长度为 n n n,表示 n n n个服务员,每服务一个顾客的时间。

给定一个正数 m m m,表示有 m m m个人等位,如果你是刚来的人,每个客人遵循有空位就上的原则,请问你需要等多久?假设 m m m远远大于 n n n,比如 n < = 1 0 3 n <=10^3 n<=103, m < = 1 0 9 m <= 10^9 m<=109,该怎么做是最优解?【谷歌一连考了好几个月,很经典的情景题】

问题分析:

我们记等待时间为 t i m e time time,如果 t i m e time time和某个变量具有函数单调性,那么就可以对 t i m e time time进行二分。经历前五道题的磨炼我们知道,“某个变量”一定要和题目中给的条件扯上关系。

根据题目条件,服务员的个数以及每个服务员服务客户的时间是固定的,也就是说,这家餐厅在单位时间内的客户接待量是固定的【我们假设服务场景发生的餐厅,这个假设无关紧要,只是方便大家去理解】,排在我前面的顾客数量 m m m越大,那我们就需要等待更多的时间,换而言之,

​ 如果排在我前面的顾客数量为 m m m时,我们需要等待 t i m e 1 time_1 time1时间,那当排在我前面的顾客数量为 n , n < m n,n<m n,n<m时,我们需要等待的时间 t i m e 2 time_2 time2一定不会大于 t i m e 1 time_1 time1

根据上面分析我们很容易想到二分筛选条件:如果 t i m e time time时间内餐厅接待的客人个数 > = m >=m >=m,说明等待时间可以提前结束,我们选取左半部分区间来进行区间收敛 a n s w e r = m i d , r i g h t = m i d − 1 answer = mid,right = mid-1 answer=mid,right=mid1。如果 t i m e time time时间内餐厅接待的客人个数 < m <m <m,则说明在 t i m e time time时间过后仍有人在排队,我需要继续等待,所以我们选择右半部分区间来进行区间收敛 l e f t = m i d + 1 left = mid +1 left=mid+1

现在我们只需要解决下面的问题就能进行二分搜索,

​ 【问题6-1】给定时间 t i m e time time,请问餐厅在 t i m e time time时间内最多能接待多少个客人【接待指的是服务客人并结束服务, t i m e time time时刻还在接受服务的客人不参与计数】。

【问题6-1】利用贪心思想便可解决,要想服务的客人数量多,那服务员的工时就必须更长,我们就把服务员的工时拉满,全部工作 t i m e time time时间。最后只需要统计每个服务员工作 t i m e time time时间接待的顾客数,最后再求和即可。

在这里我给出【问题6-1】的解决代码:

bool check_Pro6(vector<int> arr, int time,int m) {int sum = 0;for (int i : arr) {sum += time / i;}if (sum >= m)    return true;else    return false;
}

二分筛选条件也讨论过,现在只差边界了,等待时间非负,所以左边界 l e f t = 0 left = 0 left=0,右边界可以这么去粗略确定,如果所有服务员的工作效率都和最慢的服务员一样,那么我需要等待的时间会比实际等待时间长很多,实际等待时间一定会小于 最低工作效率接待m个顾客所需要的时间。最低工作效率所需要的时间 对应着 a r r arr arr数组的最大值 m a x max max* ( m / n ) (m/n) (m/n)

解决代码:

在这里只给出主体框架二分代码:

int solution_Pro6(vector<int> arr, int m) {int max = 0;for (int i : arr) {max = i > max ? i : max;}int left = 0;int right = max * (m / arr.size());int answer;while (left <= right) {int mid = (left + right) / 2;if (check_Pro6(arr, mid, m)) {answer = mid;right = mid - 1;}else {left = mid + 1;}}return answer;
}

相关文章:

二分思想与相关问题(下)

接下来详细讲解几道比较难的例题&#xff0c;仔细体会二分和其他概念混合在一起的趣味。 下面这道题涉及了“碎片拼接”的概念&#xff0c;很妙&#xff0c;也很难想。 P r o b l e m 5 Problem5 Problem5 同时运行N台电脑的最长时间 LeetCode2141 你有 n 台电脑。给你整数 n…...

【算法专题】搜索算法

二叉树剪枝 LCR 047. 二叉树剪枝 - 力扣&#xff08;LeetCode&#xff09; 本题要求我们将全部为0的二叉树去掉&#xff0c;也就是剪枝&#xff0c;当我们举一个具体的例子进行模拟时&#xff0c;会发现&#xff0c;只关注于对其中一个子树的根节点进行剪枝&#xff0c;由于我…...

B2064 斐波那契数列

题目描述 斐波那契数列是指这样的数列&#xff1a;数列的第一个和第二个数都为 11&#xff0c;接下来每个数都等于前面 22 个数之和。 给出一个正整数 aa&#xff0c;要求斐波那契数列中第 aa 个数是多少。 输入格式 第 11 行是测试数据的组数 nn&#xff0c;后面跟着 nn 行…...

Spark的介绍

一、分布式的思想 不管是数据也好&#xff0c;计算也好&#xff0c;都没有最大的电脑&#xff0c;而是多个小电脑组合而成。 存储&#xff1a;将3T的文件拆分成若干个小文件&#xff0c;例如每500M一个小文件&#xff0c;将这些小文件存储在不同的机器上 。 -- HDFS 计算&#…...

SpringBoot项目是如何启动

启动步骤 概念 运行main方法&#xff0c;初始化SpringApplication 从spring.factories读取listener ApplicationContentInitializer运行run方法读取环境变量&#xff0c;配置信息创建SpringApplication上下文预初始化上下文&#xff0c;将启动类作为配置类进行读取调用 refres…...

科技之光,照亮未来之路“2024南京国际人工智能展会”

全球科技产业的版图正以前所未有的速度重构&#xff0c;而位于中国东部沿海经济带的江浙沪地区&#xff0c;作为科技创新与产业升级的高地&#xff0c;始终站在这一浪潮的最前沿。2024年&#xff0c;这一区域的科技盛宴——“2024南京人工智能展会”即将在南京国际博览中心盛大…...

在深度学习计算机视觉的语义分割中,Boundary和Edge的区别是?

在深度学习中的计算机视觉任务中&#xff0c;语义分割中的 Boundary 和 Edge 其实有一些相似之处&#xff0c;但它们的定义和使用场景略有不同。下面是两者的区别&#xff1a; 1. Boundary&#xff08;边界&#xff09; 定义&#xff1a;Boundary 是指一个对象或区域的边界&a…...

【JAVA入门】Day41 - 字节缓冲流和字符缓冲流

【JAVA入门】Day41 - 字节缓冲流和字符缓冲流 文章目录 【JAVA入门】Day41 - 字节缓冲流和字符缓冲流一、缓冲流的体系结构二、字节缓冲流2.1 字节缓冲流提高效率的底层原理 三、字符缓冲流 在IO流体系中&#xff0c;FileInputStream&#xff0c;FileOutputStream&#xff0c;F…...

collocate join,bucket join,broadcast join,shuffle join对比分析

在分布式计算和大数据处理中,尤其是在使用像 Apache Spark、Hive 等大数据处理框架时,Join 操作是非常常见的。根据数据分布方式和执行机制,Join 操作可以分为不同的类型,如 Collocate Join、Bucket Join、Broadcast Join 和 Shuffle Join。以下是它们的详细对比分析: 1.…...

微信自动通过好友和自动拉人进群,微加机器人这个功能太好用了

又发现一个好用的功能&#xff0c;之前就想找一个这种工具&#xff0c;现在发现可以利用微加机器人的两个功能来实现&#xff0c;分别是加好友和关键词拉群 首先 微加机器人的专业版 > 功能 > 加好友设置 可以设置一个关键词通过,这样别人加好友的时候只需要输入制定内…...

R语言统计分析——功效分析3(相关、线性模型)

参考资料&#xff1a;R语言实战【第2版】 1、相关性 pwr.r.test()函数可以对相关性分析进行功效分析。格式如下&#xff1a; pwr.r.test(n, r, sig.level, power, alternative) 其中&#xff0c;n是观测数目&#xff0c;r是效应值&#xff08;通过线性相关系数衡量&#xff0…...

Django创建模型

1、根据创建好应用模块 python manage.py startapp tests 2、在models文件里创建模型 from django.db import modelsfrom book.models import User# Create your models here. class Tests(models.Model):STATUS_CHOICES ((0, 启用),(1, 停用),# 更多状态...)add_time mode…...

盘点2024年大家都在用的短视频剪辑工具

你现在休息的时间是不是都靠短视频来消遣&#xff1f;看着看着你就会发现短视频制作好像我也可以了吧&#xff1f;这次我就介绍一些简单好操作的短视频剪辑工具。 1.FOXIT视频剪辑 连接直达>>https://www.pdf365.cn/foxitclip/ 短视频剪辑其实也不难&#xff0c;只需…...

“左侧文字横向”的QTabWidget

左侧用 QToolButton 组&#xff0c; 右侧用 QStackedWidget&#xff0c;信号槽绑定切换页面 可定制化高 QButtonGroup* btnGp new QButtonGroup(this);btnGp->addButton(ui->btn1, 0);btnGp->addButton(ui->btn2, 1);btnGp->addButton(ui->btn3, 2);connect…...

python学习之字符串操作

str python # 定义一个字符串变量 print(id(str))print(str) # 打印整个字符串 print(str[0:-1]) # 打印字符串第一个到倒数第二个字符&#xff08;不包含倒数第一个字符&#xff09; print(str[0]) # 打印字符串的第一个字符 print(str[2:5]) # 打印字符串第三到第…...

第7篇:【系统分析师】计算机网络

考点汇总 考点详情 1网络模型和协议&#xff1a;OSI/RM七层模型&#xff0c;网络标准和协议&#xff0c;TCP/IP协议族&#xff0c;端口 七层&#xff1a;应用层&#xff0c;表示层&#xff0c;会话层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层&#xff0c;…...

无人机培训机构组装调试技术详解

一、基础知识学习 在进入无人机组装调试领域之前&#xff0c;扎实的基础知识是不可或缺的。学员需掌握以下内容&#xff1a; 1. 无人机基本原理&#xff1a;了解无人机的飞行原理&#xff0c;包括升力、推力、重力和阻力等基本物理概念&#xff0c;以及无人机的飞行控制系统&…...

‌汽车的舒适进入功能是什么意思?

移动管家汽车的舒适进入系统是指无钥匙进入功能&#xff0c;它允许驾驶者在距离车辆一定范围内自动感应解锁车辆&#xff0c;并具备无钥匙启动功能‌。舒适进入系统的核心优势包括&#xff1a; ‌智能化操作‌&#xff1a;无需传统钥匙&#xff0c;通过智能感应实现车门解锁和…...

杂七杂八-系统环境安装

杂七杂八-系统&环境安装 1. 系统安装2. 环境安装 仅个人笔记使用&#xff0c;后续会根据自己遇到问题记录&#xff0c;感谢点赞关注 1. 系统安装 Windows安装linux子系统WSL2&#xff1a;使用windows系统跑linux程序(大模型)WSL VSCode&#xff1a;VSCode连接WSL实现高效…...

Redis高可用,Redis性能管理

文章目录 一&#xff0c;Redis高可用&#xff0c;Redis性能管理二&#xff0c;Redis持久化1.RDB持久化1.1触发条件&#xff08;1&#xff09;手动触发&#xff08;2&#xff09;自动触发 1.2 Redis 的 RDB 持久化配置1.3 RDB执行流程(1) 判断是否有其他持久化操作在执行(2) 父进…...

React项目中使用发布订阅模式

React项目中使用发布订阅模式 1.创建发布订阅器2.在组件中使用发布订阅器3. 订阅数据 发布订阅模式&#xff08;也称观察者模式&#xff09;是一种管理跨组件通信的有效方式&#xff0c;尤其是在不希望直接依赖于特定组件的情况下。这种模式允许一个对象&#xff08;发布者&…...

buck boost Ldo 经典模型的默写

BUCK: BOOST: LDO: BUCK-BOOST:...

velero v1.14.1迁移kubernetes集群

1 概述 velero是vmware开源的一个备份和恢复工具&#xff0c;可作用于kubernetes集群下的任意对象和应用数据&#xff08;PV上的数据&#xff09;。github地址是https://github.com/vmware-tanzu/velero。 对于应用数据&#xff0c;可分文件级别的复制和块级别的复制。文件级…...

Qt Model/View之Model

在检查如何处理选择之前&#xff0c;您可能会发现检查模型/视图框架中使用的概念很有用。 基本概念 在模型/视图架构中&#xff0c;模型提供了一个标准接口&#xff0c;用于视图和委托访问数据。在Qt中&#xff0c;标准接口由QAbstractItemModel类定义。无论数据项如何存储在…...

如何在 Vue 3 中使用 Element Plus

在 Vue 3 中使用 Element Plus 是一个相对直接的过程&#xff0c;因为 Element Plus 是为 Vue 3 设计的 UI 组件库。以下是在 Vue 3 项目中集成和使用 Element Plus 的基本步骤&#xff1a; 1. 安装 Element Plus 首先&#xff0c;你需要在你的 Vue 3 项目中安装 Element Plu…...

【TVM 教程】在 Relay 中使用 Pipeline Executor

Apache TVM 是一个端到端的深度学习编译框架&#xff0c;适用于 CPU、GPU 和各种机器学习加速芯片。更多 TVM 中文文档可访问 → Apache TVM 中文站​tvm.hyper.ai/ 作者&#xff1a;Hua Jiang 本教程介绍如何将「Pipeline Executor」与 Relay 配合使用。 import tvm from t…...

使用mingw64 编译 QT开发流程

1. 安装QT5 QT5.12.12 安装时选择mingw的开发包 2. 使用qtdesigner 进行ui设计 生成ui文件 3. 将ui文件转换为.h 文件 uic mywindow.ui -o ui_mywindow.h代码中指向生成的 UI 对象的地方 要改成这个Form 4. 编译 创建mainwindow.cpp #include "mainwindow.h"…...

品读 Java 经典巨著《Effective Java》90条编程法则,第3条:用私有构造器或者枚举类型强化Singleton属性

《Effective Java》中的第3条编程法则主要是针对在开发过程如何实现单例模式&#xff0c;作者 Joshua Bloch 在书中给出了3种单例模式的实现方式&#xff1a;私有构造器和公有静态域、私有构造器和公有静态方法、枚举式。 什么是单例模式&#xff1f; 单例模式是一种设计模式…...

如何在Flask中处理表单数据

在Flask中处理表单数据是一个常见的任务&#xff0c;它涉及从客户端接收数据并在服务器端进行解析和处理。Flask本身不直接提供表单验证的功能&#xff0c;但它可以与WTForms等库结合使用来简化表单处理过程。不过&#xff0c;即使没有WTForms&#xff0c;你仍然可以直接通过Fl…...

9月12日的学习

练习 #include "widget.h" #include "ui_widget.h" QListWidgetItem *p; Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget),socket(new QTcpSocket(this))//给客户端指针实例化空间及关联父组件 {ui->setupUi(this);//初始化,ui-…...