首页 > 编程语言 >二分搜索算法

二分搜索算法

时间:2022-12-17 20:23:05浏览次数:32  
标签:二分 right target nums int mid 搜索算法 left

二分搜索算法适用于有序数组。如果按照暴力搜索算法,那么需要从头到尾遍历数组元素,时间复杂度为 O(n),而如果使用二分搜索,那么其时间复杂度为 O(logn),根据时间复杂度曲线图可知,二分搜索的算法效率要优于线性查找。

二分搜索的实现可以分为非递归和递归两种。

1. 非递归版本

如果使用非递归版本来实现二分搜索,那么有两种写法:

  • 左闭右闭区间
  • 左闭右开区间

1.1 左闭右闭区间

如果是左闭右闭区间,即 [left, right],那么需要遵循以下两点:

  1. 循环条件为 while(left <= right);
  2. if (nums[middle] > target)right 要赋值为 mid - 1;

例如,在下图所示的数组中查找目标元素 5:

二叉查找的实质其实就是将有序数组转化为一个二叉搜索树,如下图所示:

每一次搜索其实就是从二叉树的根节点开始向下搜索,如果目标值大于当前节点,则搜索右子树,如果目标值小于当前节点,则搜索左子树,直到搜索到叶子节点为止。所以二分搜索的时间复杂度其实就是有序数组转化为二叉搜索树后的高度。

由于二叉搜索树第一层有 \(2^{(1-1)}=2^0\) 个节点,第二层有 \(2^{(2-1)}=2^1\) 个节点,第三层有 \(2^{(3-1)}=2^2\) 个节点,故第 n 层有 \(2^{(n-1)}\) 个节点,假设数组长度为 \(m\),那么有:

\[2^0+2^1+2^2+...+2^{n-1}=m \]

根据数列求和公式,可得:

\[2^n-1=m \]

那么就有:

\[n\approx logm \]

即为二叉搜索的时间复杂度。

其代码实现如下:

int binearySearch(const 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) {
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    return -1;
}

1.2 左闭右开区间

如果是左闭右开区间,即 [left, right),那么需要遵循以下两点:

  1. 循环条件为 while(left < right);
  2. if (nums[middle] > target)right 要赋值为 mid;

例如,在下图所示的数组中查找目标元素 5:

其代码实现如下:

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

2. 递归版本

递归版本的相关代码如下:

int binearySearch(const vector<int>& nums, int start, int end, int target) {
    if (start > end) {
        return -1;
    }
    int mid = (start + end) / 2;
    if (nums[mid] == target) {
        return mid;
    } else if (nums[mid] > target) {
        return binearySearch3(nums, start, mid - 1, target);
    } else {
        return binearySearch3(nums, mid + 1, end, target);
    }
}

标签:二分,right,target,nums,int,mid,搜索算法,left
From: https://www.cnblogs.com/tuilk/p/16989473.html

相关文章

  • 关于整数二分的详解
    //查找左边界SearchLeft简写SLintSL(intl,intr){while(l<r){intmid=l+r>>1;if(check(mid))r=mid;elsel=......
  • HDU 4614 ——线段树+二分
    //题意:茜茜学姐的情人节到了!众所周知,茜茜学姐喜欢帅气的学弟,所以她当然有很多学弟送的花瓶,据不完全统计,茜茜学姐有N个花瓶(标号为0~N-1)。当然茜茜学姐也是个魅力四射......
  • 二分查找
    二分查找零、二分查找框架intbinarySearch(int[]nums,inttarget){intleft=0,right=...;while(...){intmid=left+(right-left)/......
  • 二分查找
    【二分查找】(O(logn))1.什么是二分查找二分查找也称折半查找(BinarySearch),它是一种效率较高的查找方法2.条件首先需要明确的是二分查找的对象应满足单调性,此外在查找过......
  • #yyds干货盘点# 名企真题专题: 二分查找
    1.简述:描述对于一个有序数组,我们通常采用二分查找的方式来定位某一元素,请编写二分查找的算法,在数组中查找指定元素。给定一个整数数组A及它的大小n,同时给定要查找的元素val,......
  • 四种二分查找法模板
    publicclassBinarySearch{publicstaticvoidmain(String[]args){int[]arr={1,2,3,3,3,4,5,5,7};intupper1=floor_lower(arr,3);......
  • 二分查找以及二分查找的变形
    二分查找以及二分查找的变形常规二分查找:在有序数组中找到num代码://1.常规二分查找首先需要保证这个数组是有序的//在有序数组中找到numpublicstaticboole......
  • 【LeetCode】二分法--剑指 Offer 53 - I. 在排序数组中查找数字 I
    点击直达题目内容统计一个数字在排序数组中出现的次数。示例示例1:输入:nums=[5,7,7,8,8,10],target=8输出:2示例2:输入:nums=[5,7,7,8,8,10],target......
  • atcoder beginner contest 144 Gluttony(二分答案)
    题目大意:有an,bn,我们找到an和bn每个元素的一种一一对应关系。使得min(max(ai*bi))。已知我们可以进行操作让an中的任一个元素减少1。操作数最大为k,问我们怎么操作,可以min(......
  • C语言 (数据结构)在顺序表中用二分查找和冒泡排序算法
    main.c:#include<stdio.h>#include<stdlib.h>#include"SequenceList.h"intmain(){//创建顺序表和指针SequenceListSL,*P_SL;intchoice=0;......