普通的二分查找

先引入一个最简单的二分查找吧

int binarySearch(int* nums, int numsSize, int target){int left = 0, right = numsSize-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;
}

很明显,这么写法将每次执行的区间划分为
[left .....mid -1] (mid) [mid+1....right]

那换个写法呢(结果都是正确的)?

int binarySearch_2(int* nums, int numsSize, int target){int left = 0, right = numsSize;while(left < right){int mid = left + (right - left)/2;if(nums[mid] == target){return mid;}else if(nums[mid] > target){right = mid;}else left = mid + 1;}return -1;
}

这个写法将区间分为了左闭右开型,不同于上面的左右两边都是闭区间
[left....mid) (mid) [mid+1....right)

以上两个写法的while条件,一个是left <= right,一个则是left < right

说明第一种while循环的结束条件为left > right,第二种结束条件为left == right

其原因就是因为左闭右闭的区间[i, i]是包含元素nums[i]的,而左闭右开的区间[i, i) 相当于空集。

搞清楚while循环结束时的具体情况,对我们分析边界值非常重要。

当数组中存在多个目标值时,这种方法返回的是位于中间位置那个目标值的下标,但是如果我们想获得目标值第一次出现时的下标应该怎么办呢?

获取左侧边界的二分查找

int binarySearch_3(int *nums, int numsSize, int target){int left = 0, right = numsSize - 1;while(left <= right){int mid = left + (right - left)/2;if(nums[mid] == target){right = mid - 1;}else if(nums[mid] > target){right = mid - 1;}else left = mid + 1;}return nums[left] == target? left : -1;
}

此算法while循环的结束条件为left > right,或者说是left = right + 1,如果nums[left] == target则说明我们最终找到了目标值,而且此时的left是该目标值第一次出现的位置。这种也可以换成子区间左闭右开的写法

int binarySearch_4(int *nums, int numsSize, int target){int left = 0, right = numsSize;while(left < right){int mid = left + (right - left)/2;if(nums[mid] == target){right = mid;}else if(nums[mid] > target){right = mid;}else left = mid + 1;}return nums[left] == target? left : -1;
}

获取右侧边界的二分查找

原理同上,两种写法

int binarySearch_5(int *nums, int numsSize, int target){int left = 0, right = numsSize-1;while(left <= right){int mid = left + (right - left)/2;if(nums[mid] == target){left = mid + 1;}else if(nums[mid] > target){right = mid - 1;}else left = mid + 1;}return nums[right] == target? right : -1;
}

int binarySearch_6(int *nums, int numsSize, int target){int left = 0, right = numsSize;while(left < right){int mid = left + (right - left)/2;if(nums[mid] == target){left = mid + 1;}else if(nums[mid] > target){right = mid;}else left = mid + 1;}return nums[right-1] == target? right-1 : -1;
}
int main(){int nums[6] = {1,2,2,2,3,5};printf("binarySearch_1: %d\n", binarySearch_1(nums, 6, 2));printf("binarySearch_2: %d\n", binarySearch_2(nums, 6, 2));printf("binarySearch_3: %d\n", binarySearch_3(nums, 6, 2));printf("binarySearch_4: %d\n", binarySearch_4(nums, 6, 2));printf("binarySearch_5: %d\n", binarySearch_5(nums, 6, 2));printf("binarySearch_6: %d\n", binarySearch_6(nums, 6, 2));return 0;
}

“茴香豆”的“茴”字有四种写法,可这二分法有六种写法,孔乙己,得亏你生的早啊。

[二分查找] 一:子区间界限应当如何确定相关推荐

  1. 二分查找法的实现和应用汇总

    此文转自:http://www.cnblogs.com/ider/archive/2012/04/01/binary_search.html 在学习算法的过程中,我们除了要了解某个算法的基本原理.实现 ...

  2. 二分查找(Java实现)

    二分查找:递归实现 public class BinarySearch {/*** @param arr 代查找的数组,需要有序* @param left 查找区间的左界限* @param right ...

  3. 二分查找以及数组下标的移动规律

    二分查找算法 复杂度log⁡2N\log_2Nlog2​N 二分查找的前提是待查找的序列必须是有序的.另外一点,C++中的序列都是前闭后开的.如果使用STL,默认是递增顺序,递减的顺序需要自定义比较函 ...

  4. java二分查找范围区间_二分查找(Java实现)

    二分查找:递归实现 public class BinarySearch { /** * @param arr 代查找的数组,需要有序 * @param left 查找区间的左界限 * @param r ...

  5. 快速排序和二分查找时间复杂度详解

    因为二分查找每次排除掉一半的不适合值,所以对于n个元素的情况:一次二分剩下:n/2两次二分剩下:n/2/2 = n/4...m次二分剩下:n/(2^m)在最坏情况下是在排除到只剩下最后一个值之后得到结 ...

  6. 【查找】- 二分查找

    懒猫老师-二分查找基础知识 代码随想录-二分查找基础知识 1 完全有序 1.1 二分查找 二分查找-力扣题目链接 1.1.1 二分查找 (左闭右闭区间) 1.循环退出条件 注意是 low<=hi ...

  7. 二分查找 归并排序 快排 详解C++

    这三个排序算法一直是面试的重点,大多数都是C语言写的,今天整理了一下C++的写法,思想都差不多.这几个排序经常忘记,今天抽空记在这,以便自己以后查阅,不对的地方,也欢迎大家评论,不吝指正,谢谢! 二分 ...

  8. 【代码随想录算法练习】| DAY01 | JavaScript | 数组理论基础,704. 二分查找,27. 移除元素

    详细解析:请看Carl老师的讲解 数组基础理论 下标从 0 开始 内存空间地址是连续的 增删元素时,会涉及其他元素地址的变动 704. 二分查找 | 点击查看力扣对应题目 二分法,也叫折半查找法,这里 ...

  9. 17道题带你理解二分查找

    不太会的可以先看看二分查找的模板 点这里 最需要注意的是二分查找的分界线并不止局限于大于等于小于,而是对某种性质的一种分界 1.Leetcode704. 二分查找 class Solution {pu ...

最新文章

  1. ios实例开发精品源码文章推荐
  2. Nat. Commun. | 深度学习探索可编程RNA开关
  3. Ural 1018 (树形DP+背包+优化)
  4. linux下关于mysqldump备份的.sql导入数据库表数据丢失优化
  5. Mastercam X9中文版
  6. 机器视觉 · 工业镜头
  7. Java VisualVM插件地址
  8. python openpyxl读写xlsx_python高阶教程-python操作xlsx文件(openpyxl)
  9. java 高效批量插入 sqlserver 数据库
  10. 多核电脑的配件(CPU)
  11. 因为10万元 乐视云计算又把自己折腾成失信被执行人...
  12. 【算法导论】0-1背包问题 与 部分背包
  13. 爬虫实例十一 全国城市房价排行
  14. 线性表的链式存储结构-----链表
  15. java 凸包算法_JAVA凸包算法
  16. LintCode 介绍
  17. 【AI创新者】图森未来CTO侯晓迪:定义问题比解决问题更重要
  18. BootStrap4内容系列之文字排版
  19. 论坛议程|COSCon'22 大数据(D)
  20. 5月9日机构对金融市场观点汇总

热门文章

  1. 运行 composer update,提示 Allowed memory size of bytes exhausted
  2. VBA Editor Addins -- VBE插件模板开发众筹
  3. OpenNebula学习第三节之虚拟机管理
  4. Apache OFBIZ高速上手(二)--MVC框架
  5. 关于使用REST API
  6. 留言本的漏洞挖掘总结
  7. SliverLight Web part
  8. python小括号报错_Python学习记录:括号配对检测问题
  9. Linux-鸟菜-5-目录配置-FHS
  10. 二分于最大流之间的关系