二分查找原理及使用场景

news2024/11/15 15:28:03

建议使用左闭右开区间[l, r)查找。二分查找的最后,索引l,r会落到右区间第一个元素位置。因此但凡是能够见数组分成左右两个区间的都能应用二分查找法。

1、普通查值

常见问题方式:寻找含重复值的有序数组 `[...,a, tar, tar, tar,.b....]`,找到tar元素的上下边界位置。

(1)寻找下边界:

俗称lower_bound,将[...a]看做左区间,[tar,tar,tar,b...]看做右区间,因此左区间向右移动的条件是nums[mid] < tar,否则右区间向左移动;(如果找不到,右区间第一个大于tar的元素)。

int lower_bound(int[] nums, int n, int tar)
{
    int left = 0, right = n;
    while(left < right)
    {
        int mid = left + (right-left)/2;
        if(nums[mid]<tar) left = mid+1;
        else right = mid;
    }
    return left;//查找结束后,不管找没找到目标值,right==left,返回哪个都行。
}

(2)寻找上边界

俗称upper_bound,将[...a,tar,tar,tar]看做左区间,[b...]看做右区间,upper bound是l-1。因此左区间向右移动的条件是nums[mid] <= tar,否则右区间向左移动;(如果找不到,右区间第一个大于tar的元素)。

2、旋转数组查找

含义:对于[1 2 3 4 5]向右旋转两次为[4 5 1 2 3]称为旋转数组。

(1)无重复元素时 查找指定元素位置

33. 搜索旋转排序数组

思路:对于[1 2 3 4 5],[4 5 1 2 3]两种旋转数组类型,可以根据target与nums[0]大小关系分成左右两区间。当target在左区间(tar>-nums[0])时,nums[mid]在右区间或在左区间但大于target都要向左移动,只有nums[mid]在左区间且小于taget向右移动。当taget在右区间同理分析。

平均时间复杂度O(logn),最坏时间复杂度O(n)

    int search(vector<int>& nums, int target) {
        if (nums.empty()) return -1;
        if (target == nums[0]) return 0;

        int n = nums.size(), l = 0, r = n;
        while (l < r) {
            int mid = (l+r)/2;
            if (nums[mid] == target) {
                return mid;
            }
            if (target >= nums[0]) {//target在左区间
                //当前值在左区间且当前值小于目标值往右走
                if (nums[mid] >= nums[0] && nums[mid] < target)
                    l = mid +1;
                else//其他情况都往左走 
                    r = mid;
            }
            else {
                //当前值在右区间且当前值大于目标值往左走
                if (nums[mid] <= nums[0] && nums[mid] > target) 
                    r = mid;
                else
                    l = mid +1;
            }
        }
        return -1;
    }

(2)含重复元素时 查找元素位置

81. 搜索旋转排序数组2

旋转数组含有重复元素,且重复元素在数组首尾时,就无法根据taget与nums[0]关系分成左右区间了,我们可以左右收缩派出重复元素,再根据上一题思路进行查找。

    bool search(vector<int>& nums, int target) {
        int n = nums.size(), l=0, r=n-1;
        if (target == nums[0]) return true;//因为要跳过首尾重复元素,先判断下

        while (l+1 <n && nums[l] == nums[l+1]) ++l;
        while (r-1>=0 && nums[r] == nums[r-1]) r--;
        if (l >= r) return false;//全部重复
        if (nums[l] == nums[r]) --r;//上面收缩后仍有可能左右边界元素相同
        ++r;//右边界取不到

        int begin = nums[l];
        while (l < r) {
            int mid = (l+r)/2;
            if (target == nums[mid]) {
                return true;
            }
            if (target >= begin) {
                if (nums[mid] >= begin && nums[mid] < target) l = mid+1;
                else r = mid;
            }
            else {
                if (nums[mid] < begin && nums[mid] > target) r = mid;
                else l = mid+1;
            }
        }
        return false;
    }

(3)无重复值 寻找最小值

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

二分法是数组按某种规律分成两个区间就可以用,最终索引落到右区间第一个元素。

该题两种情况:3 4 5 1 2       [3 4 5]向右 [1 2]向左

                1 2 3 4 5       [1 2 3 4 5]向左

所以规律是nums[mid] < nums.back向左,但是和nums[0]比较不是很符合

    int findMin(vector<int>& nums) {
        int n = nums.size(), l = 0, r = n;
        while (l < r) {
            int mid = (l+r)/2;
            if (nums[mid] > nums.back()) 
                l = mid+1;
            else r = mid;
        }
        return nums[l];
    }

(4)有重复值 寻找最小值

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

同理向去处左右重复值.平均时间复杂度O(logn),最坏时间复杂度O(n)

    int findMin(vector<int>& nums) {
        int n = nums.size(), l =0, r = n-1;
        while (l<n-1 && nums[l] == nums[l+1]) 
            ++l;
        while (r >=1 && nums[r] == nums[r-1])
            --r;
        if (l >= r) return nums[0];

        if (nums[l] == nums[r]) --r;
        ++r;
        int end = r;
        while (l < r) {
            int mid = (l+r)/2;
            if (nums[mid] > nums[end-1]) l = mid+1;
            else r = mid;
        }
        return nums[l];
    }

(5)寻找峰值元素

对于单峰值数组。有三种情况,峰值在中间,递增数组、递减数组。根据趋势将数组分为左右区间

    int findPeakElement(vector<int>& nums) {
        int n = nums.size(), l = 0, r=n;
        while (l < r) {
            int mid = (l+r)/2;
            //把n-1放到右区间,如果数组一直递增,那么l最终落到n-1上符合题目
            if (mid+1<n && nums[mid] < nums[mid+1]) l = mid + 1;
            else r = mid;
        }
        return l;
    }

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

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

相关文章

AI制药 - RCSB PDB 数据集的多维度分析与整理 (1)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/130089781 整体&#xff1a; RCSB PDB 数据集是一个收集了蛋白质的三维结构信息的数据库&#xff0c;是世界蛋白质数据库&#xff08;…

SQL SERVER调Web Service时候权限错误的解决

日期 2023/4/15 18:00:00 日志 作业历史记录 (AIPACS) 步骤 ID 1 服务器 GOOGLE 作业名称 AIPACS 步骤名称 RUNWS 持续时间 00:00:00 SQL 严重性 16 SQL 消息 ID 15281 已通过电子邮件通知的操作员 已通过…

MATLAB 基于空间格网的点云抽稀 (3)

MATLAB 基于空间格网的点云抽稀 (3) 一、实现效果二、原理步骤三、代码实现四、重点函数与对象的解释说明4.1 indices= pcbin(incloud,[rowNum colNum LayerNum]);4.2 occupancyGrid = cellfun(@(c) ~isempty(c), indices);4.3 outpointIndex = [];4.4 outpointIndex(end+1) …

基于ubuntu18.04上搭建OpenWRT-rtd1619环境

下载OpwnWRT的源码 下载路径&#xff1a;https://gitee.com/yangquan3_admin/rtd1619 您需要以下工具来编译 OpenWrt&#xff0c;包名称因发行版而异。 在 Build System Setup 文档中可以找到包含特定于发行版的软件包的完整列表。 binutils bzip2 diff find flex gawk gcc-6…

【Linux进阶篇】系统网络附加存储

目录 &#x1f341;NFS &#x1f342;软件安装 &#x1f342;服务端配置 &#x1f342;客户端配置 &#x1f342;访问浏览器测试 &#x1f341;iscsi &#x1f342;服务器端安装软件 &#x1f342;服务器端配置iscsi &#x1f342;客户端软件安装配置 &#x1f341;常用的端口号…

这6个免费去水印工具,一定要码住!

现在很多平台会在用户保存图片/视频的时候自动给视频添加一个平台的水印&#xff0c;这在一定程度上影响了它的美观和使用。 下面我来分享几个图片/视频一键去水印方法&#xff0c;操作简单还不会损坏画质哦&#xff01; 1. Magic Eraser 这是一个魔术橡皮擦在线网站&#x…

一文了解API接口自动化测试:让你在人才市场上无往不利

目录&#xff1a;导读 引言 架构 接口测试 API自动化测试 前后端分离的开发模式 测试工作&#xff1a; 协议 网络分层 三次握手的设计(很重要) 问题&#xff1a; URL:统一资源定位符 HTTP协议 &#xff08;重点&#xff09;HTTP的完整请求流程&#xff1a; 通信模…

springboot项目集成JWT实现身份认证(权鉴)

一、什么是JWT JSON Web Token (JWT)&#xff0c;它是目前最流行的跨域身份验证解决方案。现在的项目开发一般都是前端端分离&#xff0c;这就涉及到跨域和权鉴问题。 二、JWT组成 由三部分组成&#xff1a;头部(Header)、载荷(Payload)与签名(signature) 头部&#xff08;Head…

[测试新人必看] 测试报告如何编写? 掌握这五十个测试报告模板

作为一个曾经是测试萌新的我&#xff0c;在首次接收到一个任务时总有一种忐忑慌张激动紧张期望的复杂情绪~~ 忐忑慌张紧张是怕自己做不好&#xff0c;得不到领导的赏识&#xff1b;激动期望是哇塞&#xff0c;我有任务了耶&#xff0c;终于有我的用武之地了~~~ 就好比今天的主题…

Android 实现控件对称布局(约束布局和线性布局)

画界面时会遇到很多界面上的布局&#xff0c;虽然很简单&#xff0c;但是每次做起来不熟练&#xff0c;总结一下一些日常的 一.实现界面上的两个空间对称布局 方法一、用约束布局的guideLine.适用于两个控件不确定宽高&#xff0c;且约束条件较多 Guideline是只能用在Constra…

linux安装并发送邮件

linux安装、配置并发送邮件&#xff08;以CentOS7.9为例&#xff09; 1、安装邮箱软件 yum install mailx -y2、 配置邮箱&#xff08;以qq邮箱为例&#xff09; 2.1 网页访问并登录&#xff1a;https://mail.qq.com/ 2.2 选择“设置->账户” 2.3 在账户下面找到POP3/IMAP/…

【广州华锐互动】VR数字虚拟展厅为企业提升品牌形象和知名度

VR数字虚拟展厅是一种利用虚拟现实技术来展示企业产品和服务的全新宣传方式&#xff0c;与传统展厅相比具有出色的互动功能和沉浸体验感&#xff0c;参观者可以随时随地进入虚拟环境中进行参观&#xff0c;感受全新视听觉的体验。 VR数字虚拟展厅能够带来很多优势和好处&#x…

Flink 优化(六) --------- FlinkSQL 调优

目录一、设置空闲状态保留时间二、开启 MiniBatch三、开启 LocalGlobal四、开启 Split Distinct五、多维 DISTINCT 使用 Filter六、设置参数总结FlinkSQL 官网配置参数&#xff1a; https://ci.apache.org/projects/flink/flink-docs-release-1.13/dev/table/config.html 一、…

Zookeeper源码分析——算法基础

Zookeeper高级 Paxos 算法 Paxos算法&#xff1a;一种基于消息传递且具有高度容错特性的一致性算法。 Paxos算法解决的问题&#xff1a;就是如何快速正确的在一个分布式系统中对某个数据值达成一致&#xff0c;并且保证不论发生任何异常&#xff0c; 都不会破坏整个系统的一…

回溯递归(例题+思路+代码)

题目描述 leetcode 77 思路 组合问题适合用回溯求解。 经典解法&#xff1a;for循环 内部回溯。 每次进入回溯方法时&#xff0c;先判断终止条件&#xff0c;再进行当前层的循环&#xff0c;循环进行下一层递归。 代码 class Solution {public List<List<Integer&…

【C++入门必备知识:缺省参数+函数重载+函数名修饰规则】

【C入门必备知识&#xff1a;缺省参数函数重载函数名修饰规则】 ①.缺省参数Ⅰ.概念1.全缺省参数2.半缺省参数3.使用规则4.应用场景再现 ②.函数重载Ⅰ.概念1.参数个数不同2.参数类型不同3.参数类型顺序不同4.对返回值没有要求 ③.函数名修饰规则Ⅰ.C/C的不同 ①.缺省参数 Ⅰ.…

ubuntu22.04安装pyCUDA

更多内容请查看 www.laowubiji.com 笔者近期想使用GPU进行并行计算&#xff0c;搜索之后看到需要用到pyCUDA库函数&#xff0c;所以需要在所使用的ubuntu22.04系统中部署pyCUDA库&#xff0c;没想到在部署过程中折腾了好几回&#xff0c;总算是安装成功了。简单记录过程如下&a…

从输入URL到页面展示到底发生了什么

刚开始写这篇文章还是挺纠结的&#xff0c;因为网上搜索“从输入url到页面展示到底发生了什么”&#xff0c;你可以搜到一大堆的资料。而且面试这道题基本是必考题&#xff0c;二月份面试的时候&#xff0c;虽然知道这个过程发生了什么&#xff0c;不过当面试官一步步追问下去的…

AI智能改写-文本改写人工智能

随着信息技术的不断发展&#xff0c;互联网上各种信息的海量涌现&#xff0c;万千信息竞相呈现&#xff0c;如何让自己的内容独领风骚&#xff0c;引起用户的注意和眼球&#xff1f;这时&#xff0c;一款强大的文章智能改写神器便应运而生&#xff0c;可以让您的内容变得更加独…

可能你已经刷了很多01背包的题,但是真的对01背包领悟透彻了吗?,看我这一篇,使君对01背包的理解更进一步【代码+图解+文字描述】

一.概念理解&#xff1a;什么是01背包 关于01背包的概念理解如下&#xff1a;01背包是在M件物品取出若干件放在空间为W的背包里&#xff0c;每件物品的体积为W1&#xff0c;W2至Wn&#xff0c;与之相对应的价值为P1,P2至Pn。001背包的约束条件是给定几种物品&#xff0c;每种物…