【算法题解】二分查找的经典问题解析

在这里插入图片描述

文章目录

  • 什么是二分?
  • 关于二分的一些题目
    • 1.分巧克力
      • 解题思路
      • 编写代码
    • 2.数组中数值和下标相等的元素
    • 3.0到n-1中缺失的数字
    • 4.数列分段 II
      • 解题思路
      • 编写代码
  • 总结

什么是二分?

二分是一种思想,用于有序数组中快速查找目标元素。

用动图展示一下二分查找:
在这里插入图片描述

二分查找的模版很简单,但是很多题目很难想到用二分。

关于二分的一些题目

1.分巧克力

题目描述:
在这里插入图片描述
圈出来的都是重要信息。
这道题的大致意思就是有N个小朋友,现在有K个蛋糕,这K个蛋糕,蛋糕的长和宽都给出,现在要切蛋糕,但是蛋糕必须满足一定条件,保证边长是整数,并且保证切出来的蛋糕都是一样的并且是正方形(输入的蛋糕必须保证每个小朋友都可以分到1*1的蛋糕)。

在这里插入图片描述
用上面的样例举例:

在这里插入图片描述

第一种满足要求的切法:
在这里插入图片描述
如果我们再增加到33就不满足了。
在这里插入图片描述
可以看到增加到3
3后最多可以切4个,已经不满足条件了。
所以这个例子的最大的边长就是2.

解题思路

首先,先看看这道题问的什么,这道题问的是输出可以切出来的正方形的最大边长。
这道题叫我们求边长,他问什么我们就二分什么。
这道题我们就二分边长,这道题已经给出了边长的范围了。
在这里插入图片描述
所以这道题我们应该将边的范围限制在这个范围中间,l就是1,r就是1e5,在这个范围进行二分。
那么区间我们已经划定好了,区间变换的条件是什么呢?
我们假设我们第一次二分,这个数是满足的,如果这个数是满足的,那么答案是在左边还是右边呢?很显然是在右边,因为这道题求的是最大值,如果当前的数满足左边的比当前数小的数肯定都满足,但是最佳答案肯定是当前数,所以左边的数可以不做考虑了,所以下一次二分的区间应该是当前数到r。
那么如果当前数不满足反过来肯定是要缩小范围,所以下一次二分的区间应该是l到当前数。

那么具体条件是什么呢?
题目已经给出了满足的条件了,我们只需要编写一个函数检查一下这个边长是否满足当前条件即可。
很显然,就是要求每个蛋糕切出来的蛋糕总数大于等于总人数。
即: t o t a l = ( h [ i ] / e d g e ) ∗ ( w [ i ] / e d g e ) > = k total=(h[i]/edge)*(w[i]/edge)>=k total=(h[i]/edge)(w[i]/edge)>=k
上面total就是一个for循环的事。

编写代码

#include<iostream>
using namespace std;
const int N=1e5+10;
//巧克力个数和人数
int n,k;
//   长   宽
int h[N],w[N];bool check(int num)
{//记录巧克力的个数int count=0;for(int i=0;i<n;i++){//累加第i个巧克力分成成的小巧克力count+=(h[i]/num)*(w[i]/num);}if(count>=k)return true;return false;
}int main()
{cin>>n>>k;for(int i=0;i<n;i++)cin>>h[i]>>w[i];int l=1,r=1e5;//进行二分while(l<r){//向上取整int mid=l+(r-l+1>>1);if(check(mid)) l=mid;else r=mid-1;}//输出巧克力的边长cout<<r<<endl;return 0;
}

2.数组中数值和下标相等的元素

题目描述:
在这里插入图片描述
这道题就是一个很常规的二分模版题。

编写代码:

class Solution {
public:int getNumberSameAsIndex(vector<int>& nums) {int l=0,r=nums.size()-1;while(l<=r){//找到中间数下标int mid=(l+r+1)/2;if(mid>nums[mid]) l=mid;else if(mid<nums[mid]) r=mid-1;else return nums[mid];}return -1;}
};

3.0到n-1中缺失的数字

题目描述:
在这里插入图片描述
这道题也是一个很常规的二分题。

class Solution {
public:int getMissingNumber(vector<int>& nums) {if(nums.size()==0)return 0;if(nums.size()==1)return 1;int l=0,r=nums.size()-1;while(l<r) {int mid=(l+r+1)/2;if(mid==nums[mid])l=mid;else if(mid<nums[mid])r=mid-1;}if(nums[r]!=r)return r;else return r+1;}
};

4.数列分段 II

题目描述:
在这里插入图片描述
这道题的意思就和很简单,给定一个长度为N个数组,让我们将这个数组分为M段,因为有很多种分法,所以每个分法的每段中肯定能选出最大值,所以这道题的意思就是让我们求出所有分法中的最大值的最小值。

解题思路

这道题还是延续我们第一道题的想法,这道题求的是每个每种分法的最大值的最小值,所以我们对最大值进行二分,首先我们来确定二分的范围,由于是求分段的和,所以这个和肯定不可能比这数组中最大的还小,所以二分的下限肯定是数组中的数的最小值。二分的上限是数组的和(不可能你一个段的和比整个数组的和还大吧)
二分的区间已经确定了,应该确定二分的条件了,利用一点点贪心从第一个位置开始顺序的进行分段,用一个sum来维护这个段的和,用一个seg来维护段数。
在这里插入图片描述
如果当前段的和加上下一个即将入段的数小于等于需要二分的数的话,就将这个数入段,如果大于大于当前的数,那么就开辟新的段,这里的开辟新的段只需要将seg++,然后将sum置为下一个数即可,最后看分出的段是否小于给定的段数,如果小于的话说明成立,则返回true,如果大于的话说明不成立,直接返回false。(为什么只需要小于,因为如果小于的话,指定的段数是肯定能补足的)
在这里插入图片描述

如果成立的话说明还有比这个数更小的数,则下一次二分二分的区间就是l到当前数。
如果不成立的话说明这个数足够小了,没有满足的即二分的区间是当前数到r。

编写代码

#include<iostream>
using namespace std;
const int N=1e5+10;
int n,m,a[N];bool check(int num)
{int seg=0,sum=0;for(int i=0;i<n;i++){if(sum+a[i]<=num) sum+=a[i];else{sum=a[i];seg++;}}return seg<m;
}int main()
{cin>>n>>m;int l=0,r=0;for(int i=0;i<n;i++){cin>>a[i];l=max(l,a[i]);r+=a[i];}while(l<r){int mid=(l+r)/2;if(check(mid))r=mid;else l=mid+1;}cout<<l<<endl;return 0;
}

总结

二分查找不仅是一种高效的算法,更是一种通用的解题思想。它通过每次将问题规模减半,显著提高了查找效率,尤其适用于有序数据或可以通过特定条件划分搜索空间的问题。在实际编程中,熟练掌握二分查找的应用场景和技巧,不仅能帮助解决许多算法题,还能拓宽你对算法优化的思考维度。因此,深入理解二分的原理,并善于在各种场景中运用它,是提升算法能力的重要一步。

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

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

相关文章

信息系统的生命周期

信息系统是面向现实世界人类生产、生活中的具体应用&#xff0c;是为了提高人类活动的质量、效率而存在的。信息系统的目的、性能、内部结构和秩序、外部接口、部件组成等由人来规划&#xff0c;它的产生、建设、运行和完善构成一个循环的过程&#xff0c;这个过程遵循一定的规…

【vue】指令补充+样式绑定+计算属性+侦听器

代码获取 知识总结 ⼀、指令补充 1.指令修饰符 1.1 什么是指令修饰符&#xff1f; 所谓指令修饰符就是让指令的 功能更强⼤&#xff0c;书写更便捷 1.2 分类 1.2.1 按键修饰符 keydown.enter&#xff1a;当enter键按下时触发 keyup.enter&#xff1a;当enter键抬起时触…

Jmeter脚本录制:抓取IOS手机请求包

现在移动端的项目越来越多&#xff0c;今天给大家介绍一下&#xff0c;在IOS下Jmeter如何抓包。 1、电脑连上wifi 2、Jmeter中配置“HTTP代理服务器” 1)启动Jmeter&#xff1b; 2)“测试计划”中添加“线程组”&#xff1b; 3)“测试计划”中添加“HTTP代理服务器”&…

强化学习和QLearning及GAN到底是什么关系啊

强化学习&#xff08;Reinforcement Learning&#xff09;、Q-Learning 和生成对抗网络&#xff08;GANs&#xff09;是机器学习中的三个不同概念&#xff0c;它们虽然有一些交叉&#xff0c;但本质上是针对不同问题的技术方法。下面我来详细解释它们之间的关系和区别&#xff…

Springboot 整合 Java DL4J 实现农产品质量检测系统

&#x1f9d1; 博主简介&#xff1a;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编程&#xff0c;…

图片美化SDK解决方案,赋能H5与小程序极致体验

无论是社交媒体分享、电商产品展示&#xff0c;还是个人日常生活的记录&#xff0c;一张经过精心美化的图片总能瞬间吸引眼球&#xff0c;传递出更加丰富和动人的信息。如何在不增加应用体积、不牺牲用户体验的前提下&#xff0c;为H5页面和小程序提供媲美原生APP的图片美化功能…

微信小程序-自定义组件

文章目录 微信小程序-自定义组件概述创建和使用数据、方法和属性slot 插槽默认插槽具名插槽 组件样式注意项样式隔离 数据监听组件间通信父传子子传父获取子组件实例 生命周期组件的生命周期组件所在页面的生命周期App、Page与Component生命周期对比冷启动保留当前页面和关闭当…

linux源码安装slurm以及mung和openssl

一、源码安装munge 1、编译安装munge &#xff08;1&#xff09;下载munge地址&#xff1a;https://github.com/dun/munge/releases &#xff08;2&#xff09;解压编译安装&#xff1a; 1 2 3 4 5 6 7 8 创建/data目录 复制文件munge-0.5.15.tar.xz 到/data目录下 tar -Jx…

界面耻辱纪念堂--可视元素03

更多的迹象表明&#xff0c;关于在程序里使用新的动态界面元素&#xff0c;微软的态度是不确定的&#xff0c;其中一个是仅仅需要对比一下Office97 里的“Coolbars”和“标准工具条”。Coolbar 按钮直到用户指针通过的时候才成为按钮&#xff08;否则是平的&#xff09;。 工具…

新兴的安全职业挑战

我们经常与安全专业人士交谈&#xff0c;他们希望在努力提升职业发展的同时提高自己的价值并克服组织内部的挑战。在这些谈话中&#xff0c;花费大量时间讨论公司未来将面临的安全问题并不罕见。 安全领导者希望为问题制定计划并获得领导层对其计划的支持。这通常意味着实施修…

MYSQL-windows安装配置两个或多个版本MYSQL

安装第一个mysql很简单&#xff0c;这里不再赘述。主要说说第二个怎么安装&#xff0c;服务怎么配置。 1. 从官网下载第二个MySQL并安装 一般都是免安装版了&#xff0c;下载解压到某个文件目录下(路径中尽量不要带空格或中文)&#xff0c;再新建一个my.ini文件&#xff08;或…

Reality Capture 软件安装 附下载链接

Reality Capture 软件安装 文章目录 Reality Capture 软件安装一、Reality Capture v1.4汉化版安装包下载并解压二、Epic Games Launcher安装三、设置路径并安装![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/f077210990674d9fa9c10b52338b52fe.png)四、启动Epic Ga…

Chromium 如何查找V8 引擎中JavaScript 标准内置对象

JavaScript 标准内置对象 - JavaScript | MDN (mozilla.org) 一、JavaScript 标准内置对象 本章介绍和说明了 JavaScript 中所有的标准内置对象、以及它们的方法和属性。 这里的术语“全局对象”&#xff08;或标准内置对象&#xff09;不应与 global 对象混淆。这里的“全局…

985研一学习日记 - 2024.10.11

偶尔一碗热鸡汤&#xff1a;一个人内耗&#xff0c;说明他活在过去&#xff1b;一个人焦虑&#xff0c;说明他活在未来。只有当一个人平静时&#xff0c;他才活在现在。 日常 1、6&#xff1a;00起床 √ 2、健身1h 今天练了肩部以及背&#xff0c;然后跑步半小时 3、LeetC…

Python环境搭建

Python环境搭建 1 安装Python 双击安装包 2 安装Pycharm 双击安装包,然后下一步 安装完成后重启电脑 3 破解Pycharm 启动Pycharm 破解 4 pycharm的基本配置 1.主题颜色 2. 文件语言编码 滚动鼠标滑轮ctrl&#xff0c;可以快速缩放文本字体大小。 控制台编码的格式&#x…

Qt - QMenu

QMenu 1、menu转string输出 //GlobalEnum.h #include <QObject> #include <QMetaEnum> class GlobalEnum : public QObject {Q_OBJECT public:EnumTest();enum Enum_Test{ZhangSan 0,WangWu,};Q_ENUM(Enum_Test) };#define EnumToString(e) \ QMetaEnum::fromTy…

Qt初识_通过代码创建hello world

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Qt初识_通过代码创建hello world 收录于专栏【Qt开发】 本专栏旨在分享学习Qt的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1.通过按…

c语言库文件

c语言库文件 动态库动态库制作首先生成动态库文件名使用动态库编译动态库运行删除动态库1.sudo su 静态库静态库制作需要将源文件.c转换成二进制文件.o&#xff08;重定向文件&#xff09;将重定向文件打包成静态库文件使用静态库文件 静态库和动态库的区别 库文件的概念 我们将…

老人桌面 1.3.5|专为老人设计的便捷实用桌面应用

老人桌面是一款专为老人设计的便捷实用桌面应用&#xff0c;具有超大字体设计&#xff0c;符合老人视力水平&#xff0c;撞色简洁的应用界面&#xff0c;拯救老人视觉体验。此外&#xff0c;还提供了常用的实用小工具&#xff0c;让老人能够轻松使用手机。 大小&#xff1a;5.…

vuefor循环动态展示图片不显示

问题代码如下 <div class"zjjc_list_bottom" v-for"(item, index) in zjjcList" :key"item.id"><img :src"./assets/left_blue_ (index 1) .png" alt""> </div> 理论来说是不会有问题&#xff0c;但…