二分查找是学习算法的必修之课,然而二分查找有多种实现方式,根据题目要求可以使用不同的方法来实现,如果没有理清楚这些方法之间的差别,在实现算法时很容易乱了针脚,我将二分查找的相关方法介绍如下:

简单实现二分查找的两种方法

我们先从简单入手,在一个单调递增数组(无重复值)中查找target值。
二分查找一般有两种实现方法,分别时左闭右闭左闭右开,两种方法都能够找到target值,下面我们具体来看一下这两种方法:

// 左闭右闭
//nums是数组,size是数组的大小,target是需要查找的值
// 本题通过数组下标来实现的,在有些题目中通过给定最大最小值分别对应left和right即可
int search(int nums[], int size, int target)
{int left = 0;int right = size - 1;   // 定义了target在左闭右闭的区间内,[left, right]while (left <= right) {   //当left == right时,区间[left, right]仍然有效int middle = left + ((right - left) / 2);//等同于 (left + right) / 2,防止溢出if (nums[middle] > target) {right = middle - 1;   //target在左区间,所以[left, middle - 1]} else if (nums[middle] < target) {left = middle + 1;  //target在右区间,所以[middle + 1, right]} else {  //既不在左边,也不在右边,那就是找到答案了return middle;}}//没有找到目标值return -1;
}// 左闭右开
int search(int nums[], int size, int target)
{int left = 0;int right = size; //定义target在左闭右开的区间里,即[left, right)while (left < right) {    //因为left = right的时候,在[left, right)区间上无意义int middle = left + ((right - left) / 2);if (nums[middle] > target) {right = middle; //target 在左区间,在[left, middle)中 } else if (nums[middle] < target) {left = middle + 1;} else {return middle; }} // 没找到就返回-1return -1;
}// 左闭右开优化版,将相等的情况加到right的修改中,在循环结束后return left
int search(int nums[], int size, int target)
{int left = 0;int right = size; //定义target在左闭右开的区间里,即[left, right)while (left < right) {    //因为left = right的时候,在[left, right)区间上无意义int middle = left + ((right - left) / 2);if (nums[middle] < target) {left = middle + 1;} else {right = middle; //target 在左区间,在[left, middle)中 }} return left;
}

TreeSet中floor和ceiling函数

floor(E e) 方法返回在这个集合中小于或者等于给定元素的最大元素,如果不存在这样的元素,返回null.
ceiling(E e) 方法返回在这个集合中大于或者等于给定元素的最小元素,如果不存在这样的元素,返回null.

public class TreeSetDemo {public static void main(String[] args) {// creating a TreeSet TreeSet <Integer>treeset = new TreeSet<Integer>();// adding in the tree settreeset.add(23);treeset.add(25);treeset.add(35);treeset.add(40);// getting the floor value for 13System.out.println(treeset.floor(26));      // 25System.out.println(treeset.ceiling(33));   // 35}
} 

C++中的lower_bound和upper_bound

底层实现主要是通过二分查找来进行,所以认为数组是单调递增,如果查找数组不是单调数组,最后结果可能不符合期望值。还要注意返回值是数组的下标(指针)。
lower_bound(a, a + a.size(), num):返回数组中大于等于num的下标
upper_bound (a, a + a.size(), num):返回数组中大于num的下标

#include<bits/stdc++.h>
using namespace std;
int main() {int a[] = {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4};cout << (lower_bound(a, a + 12, 4) - a) << endl; //输出 9cout << (upper_bound(a, a + 12, 4) - a) << endl; //输出 12cout << (lower_bound(a, a + 12, 1) - a) << endl; //输出 0cout << (upper_bound(a, a + 12, 1) - a) << endl; //输出 3cout << (lower_bound(a, a + 12, 3) - a) << endl; //输出 6cout << (upper_bound(a, a + 12, 3) - a) << endl; //输出 9cout << (lower_bound(a, a + 12, 5) - a) << endl; //输出 12cout << (upper_bound(a, a + 12, 5) - a) << endl; //输出 12cout << (lower_bound(a, a + 12, 0) - a) << endl; //输出 0cout << (upper_bound(a, a + 12, 0) - a) << endl; //输出 0return 0;
}

下面我们来看一下C++中lower_bound和upper_bound的底层实现:

// lower_bound,其实就是上方简单方法中的左闭右开方法
int myLowerBound(vector<int> &data, int k)
{int start = 0;int last = data.size();while (start < last) {int mid = (start + last) / 2;if (data[mid] < k) {start = mid + 1;} else {last = mid;}}return start;
}// upper_bound,将相等的情况加到了left的修改中,从而达到upper的效果
int myUpperBound(vector<int> &data, int k)
{int start = 0;int last = data.size();while (start < last) {int mid = (start + last) / 2;if (data[mid] <= k) {start = mid + 1;} else {last = mid;}}return start;
}

Python中的二分查找bisect函数

bisect 函数其实是 bisect_right 函数的别名,后者还有个姊妹函数叫bisect_left。
bisect_left函数是新元素会被放置于它相等的元素的前面,而 bisect_right返回的则是跟它相等的元素之后的位置。

import bisecta = [0, 4, 5, 7, 19, 25]# 这个返回3,是因为bisect会把新的元素放在相等元素后面即 2 + 1 = 3
a1 = bisect.bisect(a, 5)# 这个返回2,是因为bisect_left会把新的元素放在相等元素前面即原来值5的索引位置2
a2 = bisect.bisect_left(a, 5)print(a1, a2) # 3, 2

这里需要注意数组a仍然需要为有序数组

二分查找的相关内容(详细)相关推荐

  1. [LeetCode]704.二分查找及相关题目

    数组理论基础 数组理论 数组是存放在连续内存空间上的相同类型数据的集合 数组可以方便的通过下标索引的方式获取到下标下对应的数据 二维数组在内存的空间地址是连续的 二分查找 LeetCode 704.二 ...

  2. 二分查找定边界(详细解析)

    二分查找定边界 学习二分查找的过程中发现经常因为边界定的不正确导致最终结果出错,写篇博客整理一下.以下所有数组都默认是按升序排列的.Leetcode上这篇Binary Search 101总结得非常好 ...

  3. 实验题7.1 实现二分查找的算法

    [实验目的] (1)掌握查找的概念: (2)熟练掌握二分查找的原理及实现方法. [实验准备] (1)阅读教材中二分查找的相关内容: (2)熟悉二分查找的算法. [实验要求] (1)采用函数调用的方式完 ...

  4. 二分查找算法详细汇总

    二分查找算法详细汇总 文章目录 二分查找算法详细汇总 二分查找算法介绍模板 算法思想 举例说明 模板实现 (1)递归方式实现 (2)非递归方式实现 二分查找问题相关难点问题1[前缀和 + 二分查找 + ...

  5. 二分查找算法 python实现

    二分查找算法 python实现 二分查找的具体内容请看这篇文章. 二分查找需要满足的条件有两个: 1.查找的数量只能是一个 2.不能是多个 查找的对象在逻辑上必须是有序的 在个人学习算法得时候,有幸看 ...

  6. python二分查找

    python二分查找的相关代码 二分查找 二分查找 二分查找是非常基本的算法题,一定要能熟练写出 def myBinarySearch(arr,target):##边界检查if len(arr) &l ...

  7. 【Cuda并行编程之一】二分查找的探究以及Cuda的简单实现相关面试题介绍

    最近开始复习基础找工作,二分查找算是最基本而且十分重要的算法了,现在完整的解析一下,作为后面复习只用.内容分为几个部分: 一.二分查找的基本过程 折半查找技术,又称为二分查找.它的前提条件是线性表中的 ...

  8. Android studio根据文本提取出的关键词在sqlite数据库中查找相关内容

    Android studio根据文本提取出的关键词在sqlite数据库中查找相关内容 一.介绍 二.Android studio连接.操作和查看sqlite数据库 三.在数据库中查找相关内容 四.运行 ...

  9. 二分查找,超详细解读与代码实现,看完不会取关

    必要条件:给定的数组必须有序,否则不适用二分查找.如果传入的数组无序,则要先对其排序,再进行二分,查找.那排序问题可参考其它排序算法.这篇博文的重点是讲二分. 核心思路:二分区间,找到划分的区间中点位 ...

最新文章

  1. 百度推出自动驾驶系统Apollo2.0, 距商业化“更近一步”!
  2. 比特币继续回撤,BCH异动,警惕一日游行情
  3. 蓝牙模块与电脑无线通信--AD测量大电压
  4. 通过live555实现H264 RTSP直播(Windows版)
  5. 仔细想了想支持向量机(Support Vector Mechine)
  6. 大厂产品经理是如何做好用数据驱动业务增长的?
  7. keil接收别人发的工程打不开_STM32工程模板建立之 KEIL 开发平台设置(一)
  8. 一道算法题:等价类思想在计数中的应用
  9. springBoot事物
  10. OpenStack版本发布周期或将延长为1年
  11. SpringBoot @Value 读取配置,太强大了!
  12. HTML系列之多媒体音频标签 audio
  13. Python基础-Week2
  14. 算法思考题-三只老鼠找8瓶毒药思路(个人思考+收集)
  15. 定义函数,实现折半查找算法
  16. SaltStack数据系统
  17. MySQL 使用 B+ 树的研究
  18. 查看笔记本电脑型号等数据
  19. 数说故事2022年中国预制菜行业趋势及营销创新洞察报告
  20. 中学教师资格考试真题及答案

热门文章

  1. jquery,js实现手机端全屏轮播图手动滑动+自动切换(autoplay)
  2. 【浏览器】HTTP 缓存机制
  3. 记一次讲座与前辈的对话
  4. 定时关机命令——shutdown
  5. 网页布局的方法有哪些?
  6. 派斯宝多尼斯荣登纳斯达克大屏 闪耀国际舞台
  7. Redis之Vs Memcached
  8. 【try……catch】C++ try…… catch 笔记(C语言中也可以Try-Catch异常处理)
  9. 玩彩票赢钱概率有多少?用Python来告诉你
  10. 2022登高架设考试模拟100题模拟考试平台操作