【二分查找】--- 进阶题目赏析

 Welcome to 9ilk's Code World

       

(๑•́ ₃ •̀๑) 个人主页:         9ilk

(๑•́ ₃ •̀๑) 文章专栏:      算法Journey


本篇博客我们继续来了解一些有关二分查找算法的进阶题目。


🏠 寻找峰值

📌 题目内容

162. 寻找峰值 - 力扣(LeetCode)

📌 题目解析

  • 与山脉数组那道题不同的是,本题数组内存在多个峰值。
  • 注意本题一个规定,即num[-1] = num[n] = 负无穷,数组边界都是最小负无穷。

📌算法原理

📒  思路一:暴力解法

有三种情况下,某个数是峰值,我们暴力解法只需要遍历一遍数组进行分类情况即可,但是时间复杂度是O(N)不符合题意。

📒 思路二:二分查找

我们发现:

1. 当arr[i] > arr[i+1]时,此时左边区域一定存在峰值,因此我们要向左缩小范围。

2.当arr[i] <  arr[i+1]时,此时右边区域一定存在峰值,因此我们要向右缩小范围。

3.由于峰值位置的不确定我们需要寻找峰值,因此在寻找峰值的过程中,我们发现了二段性因此可以使用二分查找

二分过程:

1. arr[i] > arr[i+1]  --->  right = mid , 此时mid处可能就是峰值所以不能跳过mid。

2. arr[i] < arr[i+1]  --->  left   = mid +1 ,此时mid+1处才可能是峰值,因此可以跳过mid。

参考代码:

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

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

📌 题目内容

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

📌 题目内容

  • 注意题目数组中的数字各不相同。

📌算法原理

📒 思路一:暴力解法

暴力解法思路很简单,可以定义一个min变量,遍历一遍数组,遇到比他小的就更新min,时间复杂度是O(N),并不符合题目要求。

📒 思路二:二分查找

题目要我们找旋转排序数组中的最小值,这个位置是“确定”的,整个数组的大小变化趋势如上图。以D为参考点,我们发现:

1.  最小值所在位置的左边,都是严格大于等于数组最后一个数的。

2.最小值所在位置的右边,都是小于等于数组最后一个数的。

3.本题要我们求的很明显地划分了两段区间,体现了二段性,我们要做的是思考如果mid落在划分的两段区间内,我们如何靠近目标

二分流程:

1. 当nums[mid] > nums[n-1]时,说明mid处于AB段,此时我们需要向右缩小范围,left = mid+1.

2.当nums[mid] <= nums[n-1]时,说明mid位于CD段,此时我们需要向左缩小范围,由于目标在CD段上,因此更新right时我们不能跳过mid因为mid可能就是最小值

参考代码:

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

思考:我们划分两端区间是以D为参考点,那么我们是否能以A为参考点呢?

1. A~B段是大于等于nums[0](A点)的,而C~D段是严格小于nums[0]的。

2.此时二分流程:

A - B : nums[i]>=nums[0] --> left= mid +1;
C - D : nums[i] < nums[0] --> right = mid;
3.当旋转数组旋转到原来升序时:

此时A点就是最小值,区间不断向右,此时就会丢掉最小值,因此对于这种边界情况我们需要特殊处理。

class Solution {
public:int findMin(vector<int>& nums) {int  left = 0;int right = nums.size() - 1;if(nums[0] < nums[right])return nums[0];int x = nums[0]; //以A为参照while(left < right){int mid = left + (right - left) / 2;if(nums[mid] >= x )left = mid + 1;else right = mid;}return nums[left];  }};

🏠 0~n-1中缺失的数字

📌 题目内容

LCR 173. 点名 - 力扣(LeetCode)

📌 题目内容

  • 注意:对于[0,1,2,3,4]这样的数组,此时缺失的数字应该为5.

📌算法原理

📒 思路一:哈希表

由于缺了一个数字,因此总的人数为数组元素个数+1,此时我们先遍历一遍数组进行映射,再从0-N遍历,没有映射的就是缺失的数字。

class Solution {
public:int takeAttendance(vector<int>& records) {unordered_map<int,int> mp;for(const auto& e : records){mp[e]++;}int reasult = 0;int n = records.size() + 1; for(int i = 0 ; i < n ; i ++){if(mp[i] == 0){reasult = i;break;}}return reasult;}
};

📒 思路二:直接遍历找结果

由于学号从0开始,因此数组中每个数都应该与下标相同,由于缺失了一个数,可能导致它的下一个数占它的位置,也可能他就是最后一个数。

class Solution {
public:int takeAttendance(vector<int>& records) {bool flag = false;int i = 0;for( i = 0 ; i < records.size();i++){if(i != records[i]){flag = true;break;}}return i;}
};

📒 思路三:位运算

既然知道应到同学的人数n,又根据按位异或a^a = 0 的性质,我们可以用ret遍历一遍数组进行异或,再从0-N异或,最后ret就是缺失的数字。

class Solution {
public:int takeAttendance(vector<int>& records) {int n =  records.size();int sum = 0;for(int i = 0 ;i <= n ;i++){sum ^= i;}for(int i = 0; i < records.size();i++){sum ^= records[i];}return sum;}
};

📒 思路四:高斯求和公式

由于我们知道了应到学生人数,因此我们可以用等差数列求原本应该的学号之和,再遍历数组减去,最后得到的就是缺失的数字。

class Solution {
public:int takeAttendance(vector<int>& records) {int n =  records.size() + 1;int sum = 0 + (n*(n-1)) / 2;cout << sum <<endl;for(int i = 0; i < records.size();i++){sum -= records[i];}return sum;}
};

📒 思路五:二分查找

前面的思路都很简单,但时间复杂度都是O(N)。仔细观察我们发现因为缺失了数字,会造成二段性。

我们发现,由于缺失了一个数字造成了二段性:

1. 左边一段区间的值都与下标相同,而右边一段区间的值与下标不匹配,因此我们需要去靠近第一个不与下标匹配的值。此时这个值的下标就是缺失的数字。

2.nums[mid] = mid时,说明mid在左边,此时需要向右缩小范围。

3.nums[mid] ≠ mid时,说明mid在右边,此时mid可能就是我们要找的,因此不能跳过mid.

4.需要注意的是对于类似[0,1,2,3,4]这样的情况,最后left==right时,我们需要返回left+1.

参考代码:

class Solution {
public:int takeAttendance(vector<int>& records) {int left = 0;int right = records.size() - 1;while(left < right){int mid = left + (right - left ) / 2;if(records[mid] == mid)left = mid + 1;elseright = mid;       }if(records[left] != left) return left;return left + 1; }
};

总结:

1. 当题目很明确要求的目标能划分二段性时,我们需要考虑的是在划分区间内怎么接近目标。

2.当不是很明确二段性时,我们要考虑的是在找目标的过程中能否发现二段性。

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

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

相关文章

【python爬虫】邮政包裹物流查询2瑞数6加密

大家好呀&#xff0c;我是你们的好兄弟【星云牛马】&#xff0c;今天给大家带来的是瑞数6的补环境的总结&#xff0c;补环境肯定是需要一些基础补环境知识的&#xff0c;所以建议没有基础的小伙伴可以加入学习群进行学习&#xff0c;有基础的伙伴加入交流起来。 QQ群&#xff…

用C#写一个随机音乐播放器

form1中namespce里的代码如下 public partial class Form1 : Form {public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){string folder textBox1.Text;string folderPath folder; // 指定音频文件所在的文件夹路径OpenRandomFi…

thinkphp5漏洞分析之文件包含

目录 一、环境 二、开始研究 三、漏洞分析 四、漏洞修复 五、攻击总结 一、环境 thinkphp官网下载 创建 application/index/view/index/index.html 文件&#xff0c;内容随意&#xff08;没有这个模板文件的话&#xff0c;在渲染时程序会报错&#xff09; 二、开始研究 创…

后端开发刷题 | 链表内指定区间反转【链表篇】

描述 将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转&#xff0c;要求时间复杂度 O(n)O(n)&#xff0c;空间复杂度 O(1)O(1)。 例如&#xff1a; 给出的链表为 1→2→3→4→5→NULL1→2→3→4→5→NULL, m2,n4 返回 1→4→3→2→5→NULL 数据范围&#xff1a; 链表…

java使用itext 直接生成pdf

itext 使用 需求背景itext 的使用依赖简单示例基础设置&#xff08;页面大小、边距、字体等&#xff09;段落内部&#xff0c;特殊设置关键字 字体或颜色生成动态表格页脚展示页数其他设置密码添加水印&#xff08;背景图&#xff09;目录Header, Footer分割 PDF合并 PDF 需求背…

Oracle+ASM+High冗余详解及空间计算

Oracle ASM&#xff08;Automatic Storage Management&#xff09;的High冗余模式是一种提供高度数据保护的策略&#xff0c;它通过创建多个数据副本来确保数据的可用性和安全性。 以下是关于Oracle ASM High冗余的详细解释&#xff1a; 一、High冗余的特点 1.数据冗余度 在Hi…

ThreadLocal 详解

文章目录 1.什么是Thradlocal2.Thradlocal常见的API3.什么是内存溢出与内存泄漏内存溢出 (Memory Overflow)内存泄漏 (Memory Leak) 4.强 软 弱 虚引用实现区别5.Threadlocal原理分析set方法get方法 6.Threadlocal产生内存泄漏问题断点查看变化 1.什么是Thradlocal ThreadLoca…

Golang基于DTM的分布式事务TCC实战

Golang基于DTM的分布式事务SAGA实战-CSDN博客 源代码&#xff1a;https://github.com/Ssummer520/dtm-gin 我们可以通过canal来监听转账表的binlog来看数据库变更docker-compose 安装canal-CSDN博客 代码在宿主机运行 docker network:bridge docker安装,安装成功后可以访问h…

python提取b站视频的音频(提供源码

如果我想开一家咖啡厅&#xff0c;那么咖啡厅的音乐可得精挑细选&#xff01;又假设我非常喜欢o叔&#xff0c;而o叔只在b站弹钢琴&#xff0c;那这时候我就得想方设法把b站的视频转为音频咯&#xff01; 一、首先打开网页版bilibili&#xff0c;按F12&#xff1a; 二、刷新页面…

力扣爆刷第174天之TOP200五连刷136=140(最小k数、字典序、跳跃游戏)

力扣爆刷第174天之TOP200五连刷136140&#xff08;最小k数、字典序、跳跃游戏&#xff09; 文章目录 力扣爆刷第174天之TOP200五连刷136140&#xff08;最小k数、字典序、跳跃游戏&#xff09;一、LCR 159. 库存管理 III二、450. 删除二叉搜索树中的节点三、440. 字典序的第K小…

【Spark集群部署系列一】Spark local模式介绍和搭建以及使用(内含Linux安装Anaconda)

简介 注意&#xff1a; 在部署spark集群前&#xff0c;请部署好Hadoop集群&#xff0c;jdk8【当然Hadoop集群需要运行在jdk上】&#xff0c;需要注意hadoop&#xff0c;spark的版本&#xff0c;考虑兼容问题。比如hadoop3.0以上的才兼容spark3.0以上的。 下面是Hadoop集群部署…

【Oracle篇】统计信息和动态采样的深度剖析(第一篇,总共六篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

网络协议 十一 ARP,RARP,icmp,websocket,webservice,HTTPDNS,FTP,邮件相关的协议, SMTP,POP,IMAP

ARP 已知IP 求 MAC 的过程 RARP 已知MAC 求 IP 的过程&#xff0c;已被DHCP取代 ICMP websocket 协议&#xff0c;html5中提出的前端使用协议 webservice 技术&#xff0c;已过时 HTTPDNS 之前我们要获得 某一个域名的 IP &#xff0c;要通过DNS协议 去 运营商的ISP 查询&…

计算机毕业设计 饮食营养管理信息系统 平衡膳食管理系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

一文入门re 正则表达式

一、常用方法 &#xff08;一&#xff09;匹配 一般使用方法 第一个参数&#xff1a;正则模式 第二个参数&#xff1a;需要处理的字符串 第三个参数&#xff1a;附加处理方法result从任意位置开始匹配&#xff0c;返回match&#xff0c;没有匹配到返回None result re.searc…

Linux:CentOS配置

一&#xff0c;安装VMware 这个可以通过官网获取 vmware下载 也可以联系我&#xff0c;我发给你 二&#xff0c;安装CentOS Centos官网找要下载的版本&#xff1a; https://vault.centos.org/ 阿里云镜像&#xff1a;https://mirrors.aliyun.com/centos-vault/?spma2c6h.13…

window搭建代理ip池:详细的搭建指南分享

在Windows上搭建代理IP池的指南 在进行网络爬虫或其他需要频繁请求的任务时&#xff0c;建立一个代理IP池可以有效提高抓取效率和隐私保护。本文将详细介绍如何在Windows环境下搭建一个简单的代理IP池。 1. 准备工作 在开始之前&#xff0c;请确保你具备以下条件&#xff1a…

使用Nexus3为containerd和docker配置镜像代理

1.Nexus3介绍&#xff1a; Nexus3&#xff08;Nexus Repository Manager3&#xff09;是一个用于存储、组织和管理软件组件&#xff08;如 JAR文件、npm包、Docker镜像等&#xff09;的仓库管理系统。它由Sonatype开发并维护。Nexus Repository Manger支持许多流行的包管理工具…

java 函数接口Consumer简介与示例【函数式编程】【Stream】

Java 8 中的 消费者接口Consumer 是一个函数接口&#xff0c;它可以接受一个泛型 类型参数&#xff0c;它属于java.util.function包。我们来看看Java函数接口库中的定义&#xff1a; FunctionalInterface public interface Consumer<T> {/*** Performs this operation o…

vue+elmentui 定义狂拽黑金配色的按钮+消息框

1 修改效果 通过自定义样式的方式可以修改elmentui的配色&#xff0c;例如下面我们修改掉了button的primary配色为黑金色&#xff1a; 修改前&#xff1a; 修改后 修改了elementui 的$message(success类型&#xff09;颜色为黑金色、图标也修改为金色了&#xff1a; 修改前…