专题三——二分算法

目录

原理

模板

朴素二分算法

非朴素二分算法

一二分查找

二在排序数组中查找元素的第一个和最后一个位置

三点名

四x的平方根

五搜索插入位置 

六山脉数组的峰顶索引

七寻找峰值 

八寻找旋转排序数组中的最小值


原理

定义两个指针:left指向数组第一个元素,right指向数组的最后一个元素;通过某种条件的判断,让left与right向之间靠拢;最终left与right所指的元素来确定最后的答案

模板

二分算法的实现有两个模板:朴素二分算法与非朴素二分算法

朴素二分算法

while(left <= right)
{int middle = left+(right-left)/2 //写成(right-left)/2有越界的风险if(...){left =middle + 1; }else{right = middle - 1;}}

非朴素二分算法

//左端点
while(left < right) //left <= right会越界
{int middle = left + (right - left) / 2;//left +(right - left + 1) /2会死循环if(...){left = middle + 1;}else{right = middle;}}//右端点
while(left < right) //left <= right会越界
{int middle = left + (right - left +1) / 2;if(...){left = middle;}else{right = middle - 1;}}

大部分情况的二分算法题用的都是非朴素二分算法模板来实现的!

一二分查找

oj链接:704. 二分查找 - 力扣(LeetCode)

思路:懂了模板直接套用朴素二分算法解决:

当nums[middle] < target ; left=middle + 1;else right = middle - 1

class Solution {
public:int search(vector<int>& nums, int target) {int left=0,right=nums.size()-1;while(left<=right){int middle=left+(right-left)/2;//防溢出if(nums[middle]<target){left=middle+1;}else if(nums[middle]>target){right=middle-1;}else{return middle;              }}return -1;}
};

二在排序数组中查找元素的第一个和最后一个位置

oj链接:34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

朴素二分算法解决不了,用非朴素二分模板来解决:

题目要求第一个与最后一个位置,直接用两个非朴素模板求出与target相同的左右两个端点

class Solution 
{
public:vector<int> searchRange(vector<int>& nums, int target) {//越界判断if(nums.size() == 0) return {-1 , -1};//开始元素下标(求左端点)vector<int> ans(2);int left = 0 , right = nums.size() - 1;while(left < right){int middle = left + (right - left) / 2;if(nums[middle] < target) left = middle + 1;else right = middle;}//有可能没有target if(nums[left] != target) return {-1 , -1};ans[0] = left;//最后元素下标(求右端点)//有的话在left的右边,left不用再次走到开始位置right = nums.size() -1;while(left < right){int middle = left +(right - left +1) /2;if(nums[middle] <= target) left = middle;else right = middle -1;}ans[1] = right;return ans;}
};

三点名

oj链接:LCR 173. 点名 - 力扣(LeetCode)

思路:此题的思路有很多:等差数列求和,哈希表,异或...

但这道题给出的条件适合来用二分算法解决:

判断数值与下标是否对应来进行left与right的移动 

class Solution {
public:int takeAttendance(vector<int>& records) {int left=0,right=records.size()-1;while(left<right){int middle=left+(right-left)/2;if(middle==records[middle]) left=middle+1;else right=middle;}//有可能数组里面与下标都对应上了返回后一个数字->[0,1]if(records[left]==left) return left+1;return left;}
};

四x的平方根

oj链接:LCR 072. x 的平方根 - 力扣(LeetCode) 

思路:从[1,x]中来找出符合某数的平方根<=x:如果在里面的某个值的平方根>x的,说明目标值是在这个值的左边区域,缩小范围更新right的值:是要等于它还是在它前一个位置就要自己来画图分析了;最后用非朴素模板套进去就解决本道题的求

五搜索插入位置 

oj链接:LCR 068. 搜索插入位置 - 力扣(LeetCode)

思路: 套用非朴素模板解决,注意最后结果的处理

class Solution 
{
public:int searchInsert(vector<int>& nums, int target) {int left = 0,right = nums.size() - 1;while(left < right){int middle = left +(right -left)/2;if(nums[middle] < target) left = middle + 1;else right = middle;}//left与right走到数组最后的处理if(right == nums.size() - 1 && nums[right] < target) return right + 1;else return right;}
};

六山脉数组的峰顶索引

oj链接:LCR 069. 山脉数组的峰顶索引 - 力扣(LeetCode)

 思路:山脉数组将数组分为两个区间:

左半边是递增的:arr[i] > arr[i-1](包含峰值);右半边是递减的:arr[i] < arr[i-1](不包含)

有了这个二段性,我们就可以来利用二分算法来解决问题,使得最后left与right指向峰顶

class Solution {
public:int peakIndexInMountainArray(vector<int>& arr) {int left = 0,right = arr.size() - 1;while(left < right){int middle = left + (right - left + 1) / 2;//middle在左半区间if(arr[middle] > arr[middle - 1]) left = middle;//middle在右半区间else if(arr[middle] < arr[middle -1]) right = middle -1;}return left;}
};

七寻找峰值 

 oj链接:162. 寻找峰值 - 力扣(LeetCode)

思路:要找数组其中一个峰值转化为求数组的峰值,与上面思路是一样的!

class Solution {
public:int findPeakElement(vector<int>& nums) {int left = 0,right =nums.size() - 1;while(left < right){int middle = left + (right - left) / 2;if(nums[middle] < nums[middle+1]) left = middle + 1;else if(nums[middle] > nums[middle + 1]) right = middle;}return left;}
};

八寻找旋转排序数组中的最小值

oj链接:153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode)

思路: 将旋转数组分为两段;AB段前n(旋转的次数)个数值;CD是剩余的个数;我们来拿最后一个元素(nums[n - 1])作参照物,有这样的一个规律:

AB段的值nums[i]一定>nums[n - 1];CD段的值nums[j]<=nums[n - 1];

有了二段性,我们就可以用二分算法来解决问题,只需来判断left与right的移动就完成

class Solution {
public:int findMin(vector<int>& nums) {int left = 0,right = nums.size() - 1;while(left < right){int middle = left + (right - left) / 2;if(nums[middle]>nums[nums.size()-1]) left=middle+1;else right=middle;}return nums[right];}
};

那上面的参照物能用最左边的数来解决吗?好像也类似?

问题转换为能过测试用例[1,2]和[2,1]来思考!(坑帮你们填了)QAQ 

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

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

相关文章

Redis -- 缓存雪崩问题

缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机&#xff0c;导致大量请求到达数据库&#xff0c;带来巨大压力。 可能原因 : 同一时间大量的key到期 ; 解决方案&#xff1a; 给不同的Key的TTL添加随机值 利用Redis集群提高服务的可用性 给缓存业务添加降…

渗透测试靶机----Raven-1

渗透测试靶机----Raven-1 开启靶机&#xff0c;登录窗&#xff0c;平平无奇 开扫&#xff1a; 先看看ip 这里发现192.168.217.166 发现相关服务端口&#xff0c;这里看到80&#xff0c;还是老样子&#xff0c;先80入手打开发现一个熟悉的站点&#xff1a; 这里可以使用漏扫工具…

ES学习日记(五)-------插件head安装

接上回,必要的git和node已经装完了,现在开始装head 回到es集群项目里找到plugins(插件文件夹下), 存在安装在plugins启动es报错的情况,报错信息如图一,解决方案就是换个目录,不要放在plugin目录下 git clone https://github.com/mobz/elasticsearch-head.git 打开远程登陆,默…

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现

目录 &#x1f31e;一、实验目的 &#x1f31e;二、实验准备 &#x1f31e;三、实验内容 &#x1f33c;1. 认识RMSProp算法 &#x1f33c;2. 在optimizer_compare_naive.py中加入RMSProp &#x1f33c;3. 在optimizer_compare_mnist.py中加入RMSProp &#x1f33c;4. 问…

atoi()函数---使用和模拟实现(详解)

目录 一、前言二、声明三、描述四、参数五、返回值六、使用七、模拟实现 一、前言 二、声明 int atoi(const char *str)三、描述 C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数&#xff08;类型为 int 型&#xff09;需要包含头文件&#xff…

大语言模型基石:文字与数字的起源与演变

大语言模型基石&#xff1a;文字与数字的起源与演变 1、文字 1.1、起源 我们的祖先在还没有发明文字和语言之前就已经开始使用“咿咿呀呀”的声音来传播信息了&#xff0c;比如在野外活动遇到危险&#xff0c;然后发出“咿咿呀呀”的声音来提醒同伴小心&#xff0c;同伴在接收…

考古:IT架构演进之IOE架构

考古&#xff1a;IT架构演进之IOE架构 IOE架构&#xff08;IBM, Oracle, EMC&#xff09;出现在20世纪末至21世纪初&#xff0c;是一种典型的集中式架构体系。在这个阶段&#xff0c;企业的关键业务系统往往依赖于IBM的小型机&#xff08;后来还包括大型机&#xff09;、Oracle…

基于SpringBoot+Vue的儿童书法机构管理系统

一、项目背景介绍&#xff1a; 儿童书法机构的管理是一个具有挑战性的任务&#xff0c;需要有效的信息管理和资源分配。传统的手动管理方式存在着效率低下、易出错等问题。为了解决这些问题&#xff0c;基于SpringBootVue的儿童书法机构管理系统应运而生。该系统利用现代化的技…

Linux--进程(2)

目录 前言 1. 进程的状态 1.1 进程排队 1.2 运行&#xff0c;阻塞&#xff0c;挂起 2.Linux下具体的进程状态 2.1僵尸和孤儿 3.进程的优先级 4.Linux的调度与切换 前言 这篇继续来学习进程的其它知识 上篇文章&#xff1a;Linux--进程&#xff08;1&#xff09;-CS…

ES12 学习

文章目录 1. 逻辑赋值操作符2. 数字分隔符_3. replaceAll4. Promise.any5. WeakRefs6. FinalizationRegistry 1. 逻辑赋值操作符 逻辑赋值操作符 ??、&&、|| let a true let b true a && b // a a && b a || b // a a || b obj.introduction ?…

Redis -- 缓存击穿问题

缓存击穿问题也叫热点Key问题&#xff0c;就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了&#xff0c;无数的请求访问会在瞬间给数据库带来巨大的冲击。 常见的解决方案有两种&#xff1a; 互斥锁 逻辑过期 逻辑分析&#xff1a;假设线程1在查询缓存之后&…

静态路由协议实验1

要求&#xff1a; 使用静态路由协议使得全网可达。 第一步、规划IP地址。并配置IP。 第二步、写静态路由 [r1]ip route-static 192.168.3.0 24 192.168.2.2 [r1]ip route-static 192.168.4.0 24 192.168.2.2 [r1]ip route-static 192.168.5.0 24 192.168.2.2[r2]ip route-st…

一、next-auth 身份验证凭据-使用电子邮件和密码注册登录

一、next-auth 身份验证凭据-使用电子邮件和密码注册登录 文章目录 一、next-auth 身份验证凭据-使用电子邮件和密码注册登录一、前言二、前置准备1、环境配置2、相关库安装&#xff08;1&#xff09;vercel 配置&#xff08;2&#xff09;Yarn 包管理配置 3、next项目初始化与…

【Oracle】oracle、mysql、sql server三者区别

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Oracle》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识…

Shell脚本之基础-2

目录 一、字符处理 cut命令 awk命令 sed命令 字符串排序 二、条件判断 文件类型判断 文件权限判断 两个文件的判断 整数比较 字符串判断 多重判断 三、流程控制 if分支 if else 双分支结构 case分支 for循环 while循环 一、字符处理 cut命令 命令格式&#x…

深入剖析JavaScript中的this(下)

五、事件处理函数的this 5.1 事件绑定 <button id"btn">点击我</button>function handleClick(e) {console.log(this);// <button id"btn">点击我</button> }document.getElementById(btn).addEventListener(click, handleClick…

CSS基础:4种简单选择器的详解

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。大专生&#xff0c;2年时间从1800到月入过万&#xff0c;工作5年买房。 分享成长心得。 261篇原创内容-公众号 后台回复“前端工具”可获取开发工具&#xff0c;持续更新中 后台回复“前端基础…

MySQL客户端安装并配置免密登录

最近在写脚本时需要向MySQL数据库中存储数据&#xff0c;且脚本运行的服务器与MySQL服务器不是同一台服务器&#xff0c;而且需要保证MySQL密码的安全性&#xff0c;不能在脚本中暴露&#xff0c;所以就需要在服务器上安装MySQL客户端&#xff0c;并配置免密登录。 一、虚拟机…

Git安装教程(图文安装)

Git Bash是git(版本管理器)中提供的一个命令行工具&#xff0c;外观类似于Windows系统内置的cmd命令行工具。 可以将Git Bash看作是一个终端模拟器&#xff0c;它提供了类似于Linux和Unix系统下Bash Shell环境的功能。通过Git Bash&#xff0c;用户可以在Windows系统中运行基于…

Vue项目登录页实现获取短信验证码的功能

之前我们写过不需要调后端接口就获取验证码的方法,具体看《无需后端接口,用原生js轻松实现验证码》这个文章。现在我们管理后台有个需求,就是登录页面需要获取验证码,用户可以输入验证码后进行登录。效果如下,当我点击获取验证码后能获取短信验证码: 这里在用户点击获取…