算法:二分查找

news2025/6/6 11:24:06

1.二分查找

704. 二分查找 - 力扣(LeetCode)

 二分查找算法要确定“二段性”,时间复杂度为O(lonN)。为了防止数据溢出,所以求mid时要用防溢出的方式。

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

朴素二分模版


        while(left <= right)
        {
            int mid = left + (right - left) / 2;//防溢出
            if(......)
            {
                left = mid + 1;
            }
            else if(......)
            {
                right = mid - 1;
            }
            else
            {
                return ......;
            }
        }

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

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

用二分查找解决,要查找一个区间要找去左端点和右端点。

1. 查找区间的左端点

细节处理:

        1. 循环条件 left < right 而不是left <= right ,因为left == right 的时候就是最终结果,无需判断。如果判断了就会死循环(当left和right构成的区间中存在结果,并且 nums[mid] >= t时,此时mid也等于left和right,进行上述操作的时候会导致right = mid一直在原地,所以导致死循环)。

        2. 求中点的操作

left + (right - left)/ 2 要向下取整,当剩两个点让mid的指针指向left。

2.查找区间右端点

与查找区间左端点的方法类似,只是处理条件不同。

1.当nums[mid] <= target 时left == mid。

2.当nums[mid] > target 时right == mid - 1。

循环条件:left < right 和上述原因一致。

求中点的方式 left + (right - left + 1) / 2 要向上取整,当剩两个点让mid的指针指向right。

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        if(nums.size() == 0)
            return {-1, -1};
        int left = 0, right = nums.size() - 1;
        int begin = 0;
        while(left < right)//确定区间的左端点
        {
            int mid = left + (right - left) / 2;//防溢出写法
            if(nums[mid] < target)
                left = mid + 1;
            else
                right = mid;
            
        }
        //判断是否有结果
        if(nums[left] != target)
            return {-1,-1};
        else
            begin = left;

        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;
        }
        //如果存在左端点,那么右端点也一定存在,所以不用判断了,直接返回
        return {begin, right};
        
    }
};

总结二分模版

        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(......)
                left = mid + 1;
            else
                right = mid;
            
        }

        while(left < right)//确定区间的右端点
        {
            int mid = left + (right - left + 1) / 2;
            if(......)
                left = mid;
            else 
                right = mid - 1;
        }

3. 搜索插入位置

35. 搜索插入位置 - 力扣(LeetCode)

 思路:二分查找,用左端点的模版,直接找到查找加返回要插入位置的值。如果未找到target,则检查target是否大于nums[right]:如果是,插入位置为right + 1;否则,插入位置为right(即第一个大于等于target的位置)。

class Solution {
public:
    int searchInsert(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)
                left = mid + 1;
            else
                right = mid;
        }
        if(target > nums[right])
            return right + 1;
        else
            return right;
    }
};

4. x的平方根

69. x 的平方根 - 力扣(LeetCode)

直接将1 ~ x作为查找区间,找小于等于mid*mid的x的值

class Solution {
public:
    int mySqrt(int x) 
    {
        if(x < 1) 
            return 0;
        long long left = 0, right = x;
        while(left < right)
        {
            long long mid = left + (right - left + 1) / 2;
            if(mid * mid <= x)
                left = mid;
            else
                right = mid - 1;
        }
        return left;
    }
};

5. 山脉数组的峰顶索引

852. 山脉数组的峰顶索引 - 力扣(LeetCode)

 运用二分查找算法,因为在山脉数组中,在前一段山脉arr[mid] > arr[mid - 1],在后一段山脉arr[mid] < arr[mid - 1];根据这个二段性,使用二分查找。

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

6. 寻找峰值

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

运用二分查找算法:对于区间中nums[i] 和 nums[i + 1],如果nums[i] < nums[i + 1],那么这段区间程上升趋势,因为nums[-1]和nums[n] = -\infty,所以在后一段区间内一定有峰值,让left = mid + 1.

如果nums[i] > nums[i + 1],程下降趋势,在前一段区间内一定有峰值,让right = mid。

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

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

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

 思路:使用二分查找,因为这个数组是有二段性的(要找的值为第二段的第一个元素),将这个数组分为两段第一段的值一定比第二段的值大,所以根据nums[mid]和nums[n - 1]的关系作为比较。nums[mid]>nums[n - 1],说明在mid第一段,所以要让left = mid + 1;nums[mid] <= nums[n - 1]时,说明mid在第二段上,要让right = mid。

第二种方法是一nums[0]作为比较值,只是这种有特殊情况,全是升序的时候会导致mid一直向后走,所以找特殊判断一下升序的情况。

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

        int left = 0, right = nums.size() - 1, n = nums.size();
        if(nums[n - 1] > nums[0])
            return nums[0];
        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] >= nums[0])
                left = mid + 1;
            else
                right = mid;
        }

        return nums[right];
    }
};

8.点名

LCR 173. 点名 - 力扣(LeetCode)

 1.哈希表;2.直接遍历找结构;3.位运算;4.求和公式。这些方法的时间复杂度都是O(N)。

方法5:二分查找:这个数组有二段性,分成两段判断对应的值是否相等,还需要处理一下全升序的情况

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

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

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

相关文章

Ubuntu 22.04 上安装 PostgreSQL(使用官方 APT 源)

Ubuntu 22.04 上安装 PostgreSQL&#xff08;使用官方 APT 源&#xff09; 步骤 1&#xff1a;更新系统 sudo apt update sudo apt upgrade -y步骤 2&#xff1a;添加 PostgreSQL 官方仓库 # 安装仓库管理工具 sudo apt install wget ca-certificates gnupg lsb-release -y#…

Linux随记(十八)

一、k8s的node节点磁盘 /data已使用率超过 85% , 出现disk pressure &#xff0c;驱逐pod现象 evicted &#xff0c; the node had condition:[DiskPressure] #修改/var/lib/kubelet/config.yaml ]# cat /var/lib/kubelet/config.yaml apiVersion: kubelet.config.k8s.io/v1…

Windows MongoDB C++驱动安装

MongoDB驱动下载 MongoDB 官网MongoDB C驱动程序入门MongoDB C驱动程序入门 安装环境 安装CMAKE安装Visual Studio 编译MongoDB C驱动 C驱动依赖C驱动&#xff0c;需要先编译C驱动 下载MongoDB C驱动源码 打开CMAKE(cmake-gui) 选择源码及输出路径,然后点击configure …

MS1023/MS1224——10MHz 到 80MHz、10:1 LVDS 并串转换器(串化器)/串并转换器(解串器)

产品简述 MS1023 串化器和 MS1224 解串器是一对 10bit 并串 / 串并转 换芯片&#xff0c;用于在 LVDS 差分底板上传输和接收 10MHz 至 80MHz 的并行字速率的串行数据。起始 / 停止位加载后&#xff0c;转换为负载编 码输出&#xff0c;串行数据速率介于 120Mbps…

线性调频波形测距测速信号处理——全代码+注释

clear all close all clc %% 参数设置 fs600e6;%采样率 fc10.45e9;% 波形发射载频 t10e-6;%脉宽 f050e6;%波形中频频率 B10e6;%带宽 uB/(2*t);%调频斜率 Tv100e-6;% 脉冲重复周期 Num64;% 测速脉冲数 lamdfs/B;% 抽取带宽 Nsround(fs*t); NTvround(fs*Tv); tt0:1/fs:t-1/fs; ff…

WPS word 已有多级列表序号

wps的word中&#xff0c;原来已生成的文档里&#xff0c;已存在序号。比如&#xff0c;存在2、2.1、2.1.1、2.1.1.1、2.1.1.1.1 5层序号&#xff0c;而且已分为5级。但增加内容的时候&#xff0c;并不会自动增加序号&#xff0c;应该如何解决&#xff1f; 原来长这样&#xff…

【科研绘图系列】R语言绘制论文组合图形(multiple plots)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理画图1画图2画图3画图4画图5系统信息介绍 这篇文章详细介绍了如何使用R语言进行科研绘图,特别是绘制论文组合图形(multiple plots)。文章从数…

springMVC-9数据格式化

数据格式化 学习目标&#xff1a; 理解在我们提交数据(比如表单时)&#xff0c;SpringMVC怎样对提交的数据进行转换和处理的 Spring MVC 上下文中内建了很多转换器&#xff0c;可完成大多数 Java 类型的转换工作。 基本数据类型可以和字符串之间自动完成转换 应用实例-页面…

ISBN书号查询接口如何用PHP实现调用?

一、什么是ISBN书号查询接口 ISBN数据查询接口是一项图书信息查询服务。它基于全球通用的ISBN编码系统&#xff0c;帮助用户快速获取图书的详细信息&#xff0c;包括书名、作者、出版社、出版时间、价格、封面等关键字段。 该接口广泛应用于电商平台、图书馆管理系统、二手书…

Aop + 注解实现数据字典类型转换 EasyExcel导出

Aop 注解 实现数据字典类型转换 文章目录 Aop 注解 实现数据字典类型转换一、基础方式✅字典转换简介&#x1f449;实现步骤✅ 1. 定义自定义注解Dict ✅ 2. 定义查询字典项的两个方法✅ 3. 定义Aop拦截我们查询的方法✅ 4. VO映射类✅ 5. Controller层✅ 6. serviceImpl✅ 7. …

Xilinx超过256m bit flash固件跳转失败问题

问题描述 按照 链接: Xilinx 7系列fpga在线升级和跳转 这个方式跳转失败 问题排查 进一步排查现象如下 上面这个现象呈现出明显的以16m为周期的规律。感觉很大概率是因为flash超过了16m&#xff08;256bit&#xff09;导致的地址越界问题。另外我在CSDN上也找到类似的问题…

SpringCloud 分布式锁Redisson锁的重入性与看门狗机制 高并发 可重入

可重入 Redisson 的锁支持 可重入性&#xff0c;这意味着同一个线程在获取锁后&#xff0c;如果再次尝试获取该锁&#xff0c;它可以成功地获得锁&#xff0c;而不会被阻塞。 每次一个线程成功获取锁后&#xff0c;它的持有次数会增加。当线程再次获取该锁时&#xff0c;Redi…

02 APP 自动化-Appium 运行原理详解

环境搭建见 01 APP 自动化-环境搭建 文章目录 一、Appium及Appium自动化测试原理二、Appium 自动化配置项三、常见 ADB 命令四、第一个 app 自动化脚本 一、Appium及Appium自动化测试原理 Appium 跨平台、开源的 app 自动化测试框架&#xff0c;用来测试 app 应用程序&#x…

由docker引入架构简单展开说说技术栈学习之路

想象一下&#xff0c;你开了一家线上小卖部&#xff08;单机版&#xff09;&#xff0c;突然爆单了怎么办&#xff1f;别急&#xff0c;技术架构的升级打怪之路&#xff0c;可比哆啦A梦的口袋还神奇&#xff01; 第1关&#xff1a;单枪匹马的创业初期&#xff08;单机架构&…

linux 1.0.5

环境变量到底是什么 也就是windows上面的环境变量 就是这个东东&#xff0c;用户变量和系统变量&#xff0c;那这些到底是啥呢&#xff1f; 主包只是用过&#xff0c;配置来配置去的&#xff0c;就是不知道是啥意思 windows上面的环境变量 windows的ls命令是dir 输入calc可有…

强化学习的前世今生(五)— SAC算法

书接前四篇 强化学习的前世今生&#xff08;一&#xff09; 强化学习的前世今生&#xff08;二&#xff09; 强化学习的前世今生&#xff08;三&#xff09;— PPO算法 强化学习的前世今生&#xff08;四&#xff09;— DDPG算法 本文为大家介绍SAC算法 7 SAC 7.1 最大熵强化…

生成对抗网络(GAN)基础原理深度解析:从直观理解到形式化表达

摘要 本文详细解析 生成对抗网络&#xff08;GAN&#xff09; 的 核心原理&#xff0c;从通俗类比入手&#xff0c;结合印假钞与警察博弈的案例阐述生成器 与 判别器 的对抗机制&#xff1b;通过模型结构示意图&#xff0c;解析 噪声采样、样本生成 及判别流程&#xff1b;基于…

【GitHub开源AI精选】WhisperX:70倍实时语音转录、革命性词级时间戳与多说话人分离技术

系列篇章&#x1f4a5; No.文章1【GitHub开源AI精选】LLM 驱动的影视解说工具&#xff1a;Narrato AI 一站式高效创作实践2【GitHub开源AI精选】德国比勒费尔德大学TryOffDiff——高保真服装重建的虚拟试穿技术新突破3【GitHub开源AI精选】哈工大&#xff08;深圳&#xff09;…

华为OD机试真题——文件目录大小(2025 A卷:100分)Java/python/JavaScript/C++/C语言/GO六种语言最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录+全流程解析/备考攻略/经验分享 华为OD机试真题《文件目录大小》: 目录 题…

消费者行为变革下开源AI智能名片与链动2+1模式S2B2C商城小程序的协同创新路径

摘要&#xff1a;在信息爆炸与消费理性化趋势下&#xff0c;消费者从被动接受转向主动筛选&#xff0c;企业营销模式面临重构挑战。本文提出开源AI智能名片与链动21模式S2B2C商城小程序的协同创新框架&#xff0c;通过AI驱动的精准触达、链动裂变机制与S2B2C生态赋能&#xff0…