首页 > 编程语言 >基本算法篇——二分查找

基本算法篇——二分查找

时间:2022-11-05 07:55:25浏览次数:41  
标签:二分 满足条件 int mid 算法 查找 我们

基本算法篇——二分查找

本次我们介绍基础算法中的二分查找,我们会从下面几个角度来介绍二分查找:

  • 二分查找简述
  • 二分查找模板
  • 二分查找边界
  • 例题数的范围

二分查找简述

首先我们来简单介绍一下二分查找:

  • 二分查找就是在一个数组中快速得找到我们所需要的值

  • 二分查找通常是在有单调性的数组中进行;有单调性的数组必定可以二分,但二分可以运行在没有单调数的数组中

然后我们来介绍二查找分的思想:

  1. 确定一个分界点
// 同样我们需要先确定一个分界点
// 我们的二分查找的分界点通常设计为(l+r)/2或者(l+r+1)/2,至于为什么+1我们后面讲解
  1. 确定一个查找条件
// 我们需要给出一个你查找数所满足的条件
// 我们需要确定数组的一侧不满足这个条件,但另一侧满足这个条件
// 这时我们就只需要查找这个我们需要的数,使其一侧不满足条件,而另一侧满足条件
  1. 更换边界值,不断进行递归查找
// 我们采用一种check算法来检查mid值是否满足条件,然后根据是否满足条件来判断我们所需要查找的值在哪一侧
// 然后我们更换边界值,不断进行运算,直到l==r时,这时会锁定一个数,而这个数就是我们所需要的数

二分查找模板

我们在实际使用中的二分查找模板只有两套,我们在下面给出:

  1. 第一套模板
int bsearch_1(int l,int r){
    
    // 区间[l,r]划分为[l,mid]和[mid+1,r]使用
    
    // 首先对整个数组进行遍历
    while(l < r){
        
        // 约定一个起始的分界点
        int mid = (l+r)/2;
        
        // 对该分界点进行判定
        if(check(mid)){
            // 如果满足条件时该点在[l,mid]之间
            r = mid;
        } else {
            // 如果不满足条件时该点在[mid+1,r]之间
            l = mid + 1;
        }
        
    }
    
    // 最后我们l==r,这个点就是我们二分查找出来的点
    return l;
}
  1. 第二套模板
int bsearch_1(int l,int r){
    
    // 区间[l,r]划分为[l,mid - 1]和[mid,r]使用
    
    // 首先对整个数组进行遍历
    while(l < r){
        
        // 约定一个起始的分界点
        int mid = (l+r+1)/2;
        
        // 对该分界点进行判定
        if(check(mid)){
            // 如果满足条件时该点在[mid,r]之间
            l = mid;
        } else {
            // 如果不满足条件,说明该点在[l,mid - 1]之间
            r = mid - 1;
        }
        
    }
    
    // 最后我们l==r,这个点就是我们二分查找出来的点
    return l;
}

二分查找边界

我们现在来介绍一下二分查找边界问题,也就是为什么+1:

int bsearch_1(int l,int r){
    
    // 区间[l,r]划分为[l,mid - 1]和[mid,r]使用
    
    // 首先对整个数组进行遍历
    while(l < r){
        
        // 约定一个起始的分界点
        int mid = (l+r+1)/2;
        
        // 对该分界点进行判定
        if(check(mid)){
            // 如果满足条件时该点在[mid,r]之间
            l = mid;
        } else {
            // 如果不满足条件,说明该点在[l,mid - 1]之间
            r = mid - 1;
        }
        
    }
    
    // 最后我们l==r,这个点就是我们二分查找出来的点
    return l;
}

/*
上述是+1的模板,我们+1的根本原因是因为边界问题,

因为我们将边界设置为l=mid,所以我们才需要对mid的赋值进行+1操作

因为我们的int类型是向下整分的,也就是2.5会变为2

那么如果我们的l = r - 1,这种情况下,我们的将l = mid = (l + l + 1)/2,这时l不会发生变化,我们的范围还是[l,r]不改变

因此为了避免无限循环,所以我们需要将mid的值加上0.5(1),这时我们再将l = mid,l就会向前进1,这时就不会发生循环
*/

例题数的范围

例题:

  • 我们给定一个数组,按顺序排列,我们需要得知其中某些数的起始位置和终止位置,若无该数返回-1 -1;

代码展示:

import java.util.Scanner;

public class Postion {
    public static void main(String[] args) {

        // 输入框
        Scanner scanner = new Scanner(System.in);

        // 数组长度
        int n = scanner.nextInt();

        // 查找个数
        int k = scanner.nextInt();

        // 数组内容
        int[] arr = new int[n];

        for (int i = 0; i < arr.length; i++) {
            arr[i] = scanner.nextInt();
        }

        // 开始循环
        while (k-- > 0){

            // 设置查找值
            int x = scanner.nextInt();

            // 边界设置
            int l = 0,r = n-1;

            // 开始二分查找
            while (l < r){
                // 先找左边界
                int mid = (l+r)/2;
                if (arr[mid] >= x){
                    r = mid;
                }else {
                    l = mid + 1;
                }

            }

            // 判定是否有这个数
            if (arr[l] != x){
                // 如果没有k返回return
                System.out.println("-1,-1");
            }else {
                // 如果有k,先打印左边界,我们再找右边界;(注意:此时r=l)
                System.out.println(l + " ");

                l = 0;
                r = n-1;

                while (l < r){
					// 查找右边界
                    int mid = (l+r+1)/2;
                    if (arr[mid] <= x){
                        l = mid;
                    }else {
                        r = mid - 1;
                    }
                }
            }
            // 打印右边界(注意:此时r=l)
            System.out.println(l);
        }
    }
}

结束语

好的,关于基础算法篇的二分查找就介绍到这里,希望能为你带来帮助~

标签:二分,满足条件,int,mid,算法,查找,我们
From: https://www.cnblogs.com/qiuluoyuweiliang/p/16859608.html

相关文章

  • 代码随想录第二十四天 | 回溯算法
    今天结束了二叉树的学习,开始新的一章了77.组合classSolution{List<List<Integer>>res=newArrayList<List<Integer>>();List<Integer>list=newArra......
  • 实验二:实验逻辑回归算法
    【实验目的】理解逻辑回归算法原理,掌握逻辑回归算法框架;理解逻辑回归的sigmoid函数;理解逻辑回归的损失函数;针对特定应用场景及数据,能应用逻辑回归算法解决实际分类问题......
  • leetcode Boyer-Moore 算法
    简介如何寻求一个数组中的出现次数最多的书虽然最开始想到了这个方法但是不知道如何去表达,grep就利用了这个算法classSolution{publicintmajorityElement(int[......
  • 数字n代表生成括号的对数,设计一个函数,用于能够生成所有可能的并且有效的括号组合 回溯
    题目描述:数字n代表生成括号的对数,设计一个函数,用于能够生成所有可能的并且有效的括号组合如  n=2 则输出//['(())','()()']  n=3则输出//['((()))','(()()......
  • B - K-th Number HDU - 6231 (二分 尺取)
    WindowsSource2017中国大学生程序设计竞赛-哈尔滨站题意给一个数组,在所有长度大于等于k的区间内,找出第\(k\)大的数,放到另一个数组中,然后在新数组中找到第M大的数。思......
  • 实验二:逻辑回归算法实验
    【实验目的】理解逻辑回归算法原理,掌握逻辑回归算法框架;理解逻辑回归的sigmoid函数;理解逻辑回归的损失函数;针对特定应用场景及数据,能应用逻辑回归算法解决实际分类问题。......
  • 基于GA优化的竞价博弈频谱分配算法的matlab仿真
    目录​​一、理论基础​​​​二、核心程序​​​​三、仿真测试结果​​作者ID:fpga和matlab擅长技术:1.无线基带,无线图传,编解码2.机器视觉,图像处理,三维重建3.人工智......
  • 暴力算法
    暴力算法excel(适用蓝桥杯)直接使用函数库__gcd(int,int)辗转相除法strtol(,,)转换进制枚举法小学奥数数论,分解质因数打表把所有可能的结果,先在本地存储到......
  • 倒位序算法(C#实现)
    倒位序算法(C#实现)原序数(十进制)原序数(二进制)倒位序(二进制)倒位序(十进制)000000001001100420100103301111064100001151011015......
  • 初入算法(2)—— 进入算法世界
    目录​​前言​​​​一.爆炸增量函数​​​​1.引入故事:《一棋盘的麦子》​​​​2.算法中的时间复杂度​​​​3.常见的时间复杂度类型​​​​二.兔子数列​​​​1.什么......