【刷题】 二分查找入门

在这里插入图片描述

送给大家一句话:

总有一天,你会站在最亮的地方,活成自己曾经渴望的模样—— 苑子文 & 苑子豪《我们都一样 年轻又彷徨》

二分查找入门

  • 1 前言
  • 2 Leetcode 704. 二分查找
    • 2.1 题目描述
    • 2.2 算法思路
  • 3 Leetcode 34. 在排序数组中查找元素的第一个和最后一个位置
    • 3.1 题目描述
    • 3.2 算法思路
      • 算法优化
        • 循环条件
        • 求中点的操作
  • Leetcode 35. 搜索插入位置
    • 题目描述
    • 算法思路
  • Leetcode 69. x 的平方根
    • 题目描述
    • 算法思路
  • Thanks♪(・ω・)ノ谢谢阅读!!!
  • 下一篇文章见!!!

1 前言

二分算法是一种非常强大的算法!!!
想象你在一本厚厚的字典里查找一个词。这本字典的词都是按字母顺序排列的。如果你像小学生学习拼音那样一页一页翻,肯定效率很低,因为这样你要查很久。二分查找算法就像是一个聪明的查词策略,它可以帮你快速定位到那个词。

使用二分查找时:

  1. 你会先打开字典的中间,看这一页的词是不是你要找的,如果不是,你再看这个词是在你要找的词的前面还是后面。
  2. 如果在前面,那你就把后半部分的查找范围排除掉,只在前半部分继续查找;
  3. 如果在后面,就排除掉前半部分。然后,你再在剩下的那一半中找到中间,重复之前的步骤。

通过这样一分为二,一步步缩小范围的方式,直到找到那个词,这个过程就是二分查找。
这个方法之所以有效,是因为每次查找你都排除了一半的可能性,大大提高了查找效率。就像在一个有序的环境中找东西,知道了规则,就能迅速定位,节省了大量的时间。

二分查找主要有三种模版:朴素算法,左端点算法,右端点算法。下面我们一起来通过题目认识二分查找算法吧!

2 Leetcode 704. 二分查找

上链接!!!704. 二分查找

2.1 题目描述

在这里插入图片描述
这是一一道非常经典的二分查找题目,我们来看样例:

  • 输入: nums = [-1,0,3,5,9,12], target = 9
  • 输出: 4
  • 解释: 9 出现在 nums 中并且下标为 4

很好理解二分查找的寻找过程,下面我们来看代码。

2.2 算法思路

  1. 首先先定义左右端点
  2. 判断中间是不是满足条件
  3. 如果大于那么右端点移到中间的左边
  4. 反之左端点移到中间的右边
  5. 直到找到为止

这道题无需考虑很多,使用朴素二分查找即可:

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

下面的题目我们来详细讲解左端点二分和右端点二分!

3 Leetcode 34. 在排序数组中查找元素的第一个和最后一个位置

上链接!!!34. 在排序数组中查找元素的第一个和最后一个位置

3.1 题目描述

在这里插入图片描述
这道题分别要寻找目标值的开始索引和终止索引。来看样例:

  • 输入:nums = [5,7,7,8,8,10], target = 8
  • 输出:[3,4]

3.2 算法思路

先来看暴力算法,遍历所有的元素,记录起始和终止位置既可以,但是这样就浪费了数组有序的重要特性!!!
那使用朴素算法呢? 可以是可以,但是时间复杂度会很大!遇到数组全部是目标值的时候,第一次就能命中对应目标值,但要寻找到起始和中止就要遍历所有的元素,这样就和暴力算法没有区别了!所以不推荐朴素算法

算法优化

我们来看朴素算法的优化版本:左端点二分和右端点二分
这道题实际上可以分成两个问题:

  1. 查找左端点
  2. 查找右端点

先看左端点:我们可以把数组分为两部分:小于target 的部分 ,大于等于target 的部分。然后我们分类讨论(x 为 中间值):

  1. x < t 那么 left = mid + 1 更新新区间
  2. x >= t 那么 right = mid (不能越过mid,因为mid 有可能是答案所在位置) 更新区间

在来看难点 : 循环条件 和 求中点的操作

循环条件

到底是left < right 还是 left <= right ???我们来分类讨论一下:

  1. 如果有结果,那么left 是一直想要跳出这个区域,如果相遇那么此位置就是结果(无需判断),如果判断就会陷入死循环
  2. 如果全大于 t , 那么只能right 移动,最终相遇时,如果是(left <= right )就会死循环,我们只需判断该值是否等于 t
  3. 如果全小于 t , 那么只能left 移动,最终相遇时 ,如果是(left <= right )就会死循环,我们只需判断该值是否等于 t
求中点的操作

求中点也是有两种:

  1. left + (right - left ) / 2
  2. left + (right - left + 1) / 2

如果仅剩两个元素时,使用第二种时,如x >= t 那么right 就不动了!!!陷入了死循环!!!
所以要使用第一种!!!

右端点也是同样的分析思路,不同的是:

  1. x <= t 那么 left = mid 更新新区间
  2. x > t 那么 right = mid - 1 (不能越过mid,因为mid 有可能是答案所在位置) 更新区间
  3. 求中点操作要用第二种办法
    这样就完成了:
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.size() == 0) return {-1,-1};
        int begin = 0 , end = 0;
        int left = 0, right = nums.size() - 1;
        //先找左点
        //左边都小于 t 右边大于等于 t 
        //左边不合法 右边合法
        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] < target) left = mid + 1;
            else right = mid;
        }
        if(nums[left] == target) begin = left;
        else return {-1,-1};
        //进行右边操作
        //左边都小于等于 t 右边大于 t 
        //左边合法 右边不合法
        left = 0, right = nums.size() - 1;
        while(left < right)
        {
            int mid = left + (right - left + 1) / 2;
            if(nums[mid] <= target) left = mid;
            else right = mid - 1;
        }
        end = right;
        return {begin,end};
    }
};

提交就过啦!!!

Leetcode 35. 搜索插入位置

家人们!!!上链接!!!35. 搜索插入位置

题目描述

在这里插入图片描述
这道题很好理解,找到对应位置插入即可!!!

算法思路

当然暴力算法很好想,但是我们不用。
通过上一道题的思路,我们很容易想到使用左端点二分的方法,因为插入是在该数的前面插入。

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left = 0 , right = nums.size() - 1;
        int ans = 0;
        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] < target) left = mid + 1;
            else right = mid;
        }
        //避免比最大的数大,此时是在后面插入
        if(left == nums.size() - 1 && target > nums[left]) ans = left + 1;
        else ans = left;
        return  ans ; 
    }
};

提交!过啦!!!!

Leetcode 69. x 的平方根

上链接!!!69. x 的平方根

题目描述

在这里插入图片描述

这道题很好理解奥,我们要实现找到算术平方根。即平方小于x 的最大的数。

算法思路

暴力算法很好想,一个一个试就可以,但是使用二分算法更加快速。
我们可以把数字抽象为左右端,left 为 0 right = x 。然后开始二分(判断条件是mid 的平方与x的比较)。因为是找最大的所以使用右端点二分

class Solution {
public:
    int mySqrt(int x) {
    	//初始化 右值设置为 x 的一半进一步可以避免平方超范围
        int left = 0 , right = x / 2 + 1;
        while(left < right)
        {   // 使用long long =防止超出int范围
            long long  mid = left + (right - left + 1) / 2;
            if(mid * mid <= x) left = mid ;
            else right = mid - 1 ;
        }
        return left;
    }
};

提交:过啦!!!!

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3.28号arm

can总线相关理论 1. 概念 控制器局域网&#xff08;Controller Area Network&#xff0c;CAN&#xff09;&#xff0c;其特点是可拓展性好&#xff0c;可承受大量数据的高速通信&#xff0c;高度稳定可靠&#xff0c;因此常应用于汽车电子领域、工业自动化、医疗设备等高要求…

蓝桥杯算法题-正则问题

问题描述 考虑一种简单的正则表达式&#xff1a; 只由 x ( ) | 组成的正则表达式。 小明想求出这个正则表达式能接受的最长字符串的长度。 例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是&#xff1a; xxxxxx&#xff0c;长度是 6。 输入格式 一个由 x()| 组成的正则表达式。…

广告业务知识-业务

最近做了些广告业务&#xff0c;梳理下&#xff0c;分广告术语、业务架构、数据架构三篇。下面是业务篇&#xff1a; 1.广告业务链路 先用一张图介绍下广告业务链路&#xff0c;可以理解成类似股票交易链路&#xff0c;其中ADX&#xff08;交易平台&#xff09;联系着DSP&…

Mybatis(3) web项目

web项目 1、准备2、分析3、 MyBatis对象作用域以及事务问题4、问题 实现一个转账系统 1、准备 ①准备一个web模块 在这里使用了maven archetype&#xff0c;选择web 之后会生成 一个web模块&#xff0c;但是不同的版本可能不同&#xff0c;在这里我就没有java和resources目录&…

缺陷检测项目 | 使用小数据集训练实现锅炉水冷壁管表面视觉缺陷检测

项目应用场景 面向锅炉水冷璧管表面视觉缺陷检测场景&#xff0c;项目支持训练&#xff0c;使用小数据集就能够实现很好的缺陷检测效果。 项目效果&#xff1a; 项目细节 > 具体参见项目 README.md (1) 安装依赖&#xff0c;包括 gcForest、AutoKeras&#xff0c;然后安装其…

JUC并发编程—— 对volatile的理解及DCL的解决方法

volatile的原理 volatile 的底层实现原理是内存屏障&#xff0c;Memory Barrier&#xff08;Memory Fence&#xff09; 加入 volatile 关键字后&#xff0c;写指令&#xff08;被 volatile 修饰的变量在对此变量修改时&#xff09;会加入写屏障&#xff0c;读指令&#xff08…

超图打开不同格式的dem文件

dem&#xff0c;数字高程模型&#xff1b; dem文件的后缀是什么? 有*.dem格式的&#xff0c;也有Raster&#xff0c;ASCII和Tiff类型的。Raster类型的是一个raster文件夹里面有很多不同格式的文件共同组成了DEM文件的内容。ASCII类型的是个txt文件。Tiff类型的也是一个文件夹…

[leetcode] 637. 二叉树的层平均值

给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[3.00000,14.50000,11.00000] 解释&#xff1a;第 0 层的平均值…

uniapp打包

1.小程序 需要对应上appId才可以上传还要成为该小程序的开发者开可以点击上传 2.APP打包 点击发行选择云打包&#xff0c;会弹出下方的窗口 如果公司没有给证书信息&#xff0c;就去香蕉云编去申请默认的&#xff0c;把证书文件下载出来设置路径

文献学习-24-用于少发罕见病诊断的动态特征拼接

Dynamic feature splicing for few-shot rare disease diagnosis Authors: Yuanyuan Chen, Xiaoqing Guo , Yongsheng Pan , Yong Xia , Yixuan Yuan Source: Medical Image Analysis 90 (2023) 102959 Keywords: 少样本学习 罕见病诊断 transformer 特征拼接 通道相似度 Ab…

k8s练习-创建一个Deployment

创建Deployment 创建一个nginx deployment [rootk8s-master home]# cat nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:name: nginx-deployment spec:selector:matchLabels:app: nginx # 配置pod的labelsreplicas: 2 # 声明2个副本template:metada…

开发组合:PHP+MySQL 同城社区小程序源码 同城便民信息发布系统源码 源码开源可二开含搭建教程

同城便民信息发布系统源码在提升信息发布效率、促进商家宣传、增强用户互动、实现信息聚合与分类管理、个性化定制与扩展以及数据统计与分析等方面发挥着重要作用。 今天小编给大家分享一个同城社区小程序源码、同城便民信息发布系统源码&#xff0c;开发组合PHPMySQL&#xf…

每天学点儿Python(3) -- for循环

for循环结构格式如下 for 循环变量 in 遍历对象:语句块 举例一、 for i in "Hello"print(i) 执行结果如下 举例二、 #打印100-999之间的水仙花数 #注意&#xff1a;Python中 / 除法&#xff0c;运输后为浮点数, // 为取除法后的整数&#xff0c;而不是C/C中的注释…

C++之调用Python

1、配置头文件 Python安装目录下的include目录加入头文件目录。Visual Studio2022中操作路径是&#xff1a;属性–> C/C -> 常规-> 附加包含目录 C:\Users \AppData\Local\Programs\Python\Python39\include 2、配置lib库目录 要将Python39.lib加入编译链接。Visua…

【考研数学】汤家凤基础+武忠祥强化,如何高效衔接?看这一篇!无标题】

目标分在100的话&#xff0c;建议在备考初期就把分数定在120&#xff01; 因为如果一开始就没有按高分备考&#xff0c;可能最后只能考到七八十&#xff0c;备考就尽力比自己的目标分在多高20分去准备。 本人属于基础很差相当于是零基础的考研党&#xff0c;经过一年备考成功…

SAP 修改消息号处理简介

在项目经常会遇到更改SAP消息号的地方,从警告的消息W变化报错的消息E。 通常通过TCODE:SE91来查询和创建消息号 关于消息号的几个后天表 T100:包含所有的message T100C:你定义的message通常将出现在此表 T100s:Configurable system messages顾名思义就是你能设置的消息. M…

北京WordPress建站公司

北京wordpress建站&#xff0c;就找北京wordpress建站公司 http://wordpress.zhanyes.com/beijing

代码随想录 Day31 贪心算法 理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和

目录 理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和 理论基础 1. 什么是贪心&#xff1a; 就是通过局部最优搜索全局最优 2. 贪心的两个极端&#xff1a;要么就是很简单的常识&#xff0c;要么就是很难理解的。 3. 贪心算法没有套路可言就是找局部最优&#xf…

SD-WAN组网面临的安全挑战?如何提供有效的安全措施

SD-WAN&#xff08;软件定义广域网&#xff09;技术的广泛应用&#xff0c;企业面临着越来越多的网络安全挑战。尽管SD-WAN带来了灵活性和效率的提升&#xff0c;但其开放性和基于云的特性也带来了一系列安全威胁。本文将探讨SD-WAN组网面临的安全挑战&#xff0c;并提供一些有…

如何设计一个能够支持高并发的系统?

一、问题解析 设计一个能够支持高并发的系统需要考虑多方面的因素&#xff0c;包括架构、性能优化、容错和可伸缩性等。以下是一些一般性的建议和实践&#xff1a; 1、分布式架构&#xff1a;将系统分解成多个模块&#xff0c;采用分布式架构来降低单点故障的风险&#xff0c…
最新文章