二分查找算法概述&通用模板

二分查找算法

题目要求:

给定目标值 和指定数组, 数组为升序数组 ,在数组中查找到目标值 ,如果成功返回下标,失败则返回-1。(时间复杂度尽可能短)

题目解析以及核心思路:

题目解析:

在数组中寻找目标值,只需要遍历数组一次即可, 此时的时间复杂度为O(N)。


在这里我们介绍一种快捷的查找算法--二分算法。

这种查找算法时间复杂度可以缩减到O(logN)。

算法思想: 对于某一组数组,根据题目要求的特殊规律 ,选取某点, 把数组分成两部分, 并且根据题目的特殊规律 ,舍去一组,在另一组中继续重复进行操作,直到查找到点为止。
核心思路:

特殊规律:升序数组(从中选取一个点与目标值比较:

目标值大于这个点,则一定大于左侧所有点,下一次选取点在右侧(往大的点去取)

目标值小于这个点,则一定小于右侧所有点,下一次选取点在左侧(往小的点去取))

若遇到等于情况:直接返回该点即可(就是要找的目标值)

若无法找到目标点:返回-1


细节:

  • 此处求mid使用的计算方式是"防止数据溢出",直接(left+right)/2相加很可能造成数据溢出出现数组越界的问题

代码实现:

java 复制代码
public int search(int[] nums, int target) {
        int left=0;
        int right=nums.length-1;
        while(left<=right){
            int mid=left+(right-left)/2;//防止溢出
            if(nums[mid]>target){
                right=mid-1;
            }
            if(nums[mid]<target){
                left=mid+1;
            }
            if(nums[mid]==target){
                return mid;
            }
        }
        //只要能找到一定会在上面完成返回,运行到这,已经是找不到的情况
        return -1;
    }

总结:

根据特殊规律来制定选取点与目标值的判断条件即可。

本题的二分性:升序数组->元素数值大小递增,由此来分成一个大值部分,一个小值部分

模板代码:

java 复制代码
while(left<=right){
if(//视特殊规律而定){
left=mid+1;
  }
else if(//视特殊规律而定){
right=mid-1;
  }
else{
return mid;
  }
}

查找左,右端点的二分查找算法

题目要求:

题目要求在一个给定不递减数组 中,寻找目标值的第一个出现的下标,最后一个出现的下标。

可以归结为:"寻找由指定值组成的区间的左端点和右端点"。

题目解析以及核心思路:

题目解析:

相当于寻找左,右端点。 因此我们使用两次二分查找算法,来寻找左右端点。


解题准备:

  • 二段性:若对于查找左端点,二段性为"小于t或者大于等于t";若对于查找右端点,二段性为"大于t或者小于等于t"
    核心思路:

1.查找左端点:

根据二段性:

  • 当numsmid<目标t,向右区间(更大的数)去寻找

  • 当numsmid>=目标t,向左区间(更小或者相同的数)去寻找==>当前指向数,可能就是目标值t,但是不知道其位置(前?中?末?),因此right不能越过mid(找首下标)

  • 循环条件:left<right, 循环结果是left=right时,如果再继续循环会执行第二步骤,造成死循环

  • 求中点操作:left+(right-left)/2。 数组元素个数为偶数时,取靠左的为中点,若选择靠右的为中点,会执行第二步骤,死循环


    2.查找右端点: 根据二段性:

  • 当numsmid>目标t,向左区间(更小或者相同的数)去寻找

  • 当numsmid<=目标t,向右区间(更大或者相同的数)去寻找==>当前指向数,可能就是目标值t,但是不知道其位置(前?中?末?),因此left不能越过mid(找末尾下标)

  • 循环条件:left<right, 循环结果是left=right时,如果再继续循环会执行第一步骤,造成死循环

  • 求中点操作:left+(right-left+1)/2。 数组元素个数为偶数时,取靠右的为中点,若选择靠左的为中点,会执行第一步骤,死循环


补充: 循环结束,记得判断numsleft?=target,依此为返回数组赋值

代码实现:

java 复制代码
class Solution {
    public int[] searchRange(int[] nums, int target) {
        //返回数组
        int[] a={-1,-1};
        //为空时直接返回[-1,-1]
        if(nums==null||nums.length==0){
            return a;
        }
        int left=0;
        int right=nums.length-1;
        //查找区间左端点
        while(left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]>=target){
                right=mid;
            }
            else{
                left=mid+1;
            }
        }
        //此时left==right就是结果,与目标值比较相同则返回下标
        if(nums[left]==target){
            a[0]=left;
        }
        //查找区间右端点
        left=0;
        right=nums.length-1;
        while(left<right){
            int mid=left+(right-left+1)/2;
            if(nums[mid]<=target){
                left=mid;
            }
            else{
                right=mid-1;
            }
        }
         //此时left==right就是结果,与目标值比较相同则返回下标
        if(nums[left]==target){
            a[1]=left;
        }
        return a;

    }
}

总结:

查找一个区间的左端点代码模板如左侧,查找一个区间的右端点代码模板如右侧

本人才疏学浅,若有错误还请诸位指正,希望本文能帮助到大家,后续还有关于二分查找应用的题目的博客文章,教大家如何使用模板,敬请期待。

相关推荐
xiangyun6124 分钟前
C++ priority_queue 底层:手撕二叉堆与 Top K 问题
c++·算法·面试·stl·1024程序员节
qz_Serene1 小时前
练习算法题:双指针 -cpp
c++·算法·leetcode·1024程序员节
Nuanyt2 小时前
Hot 100 刷题笔记 · 数组与哈希专题(3 题)
java·笔记·算法·leetcode·哈希算法·1024程序员节
碧海银沙音频科技研究院2 小时前
基于炬芯平台ATS308X多模型兼容语音识别算法
人工智能·算法·语音识别
爱读书的小胖2 小时前
LeetCode 274 H 指数 C 语言解题分析
c语言·算法·leetcode·1024程序员节
basketball6163 小时前
动态规划第一章:引论
算法·动态规划·1024程序员节
星夜离尘563 小时前
MATLAB 因果采样保持:用历史匹配和数据年龄防止未来信息泄漏
数据结构·算法·matlab
思麟呀3 小时前
BTree的原理与 C++ 完整实现
c语言·数据结构·c++·算法·1024程序员节
Tsuki_tl4 小时前
【优选算法 — 双指针】经典例题题解+算法总结
算法·蓝桥杯·力扣·刷题·双指针·1024程序员节·优选算法
拓恒技术5 小时前
内河航道无人机智能巡检系统与算法应用
人工智能·深度学习·算法·无人机·智慧城市