二分查找板子

二分查找实际上就是采用了分治法的思想

以下模板都以升序数组为准

模板一: 标准的二分查找#

场景:数组元素有序且不重复

有的话返回索引,没有返回-1

Copy
int binarySearch(vector<int>& arr, int target) { int left = 0, right = nums.size() - 1; while (left <= right) {//<=指可以取到右区间,是[left,right] int mid = left + ((right - left) >> 1); if (nums[mid] == target) return mid; else if (nums[mid] > target) right = mid - 1;//证明target可能在mid左侧 else left = mid + 1;//证明nums[mid] < target, target可能在mid右侧 } return -1; }

模板二:二分查找找边界#

二分查找左/有边界是二分查找的变式,一般有如下场景:

1)第一种情况

  • 数组总体有序,包含重复元素
  • 数组部分有序,且不包含重复元素

img

2)第二种情况

  • 数组部分有序,且包含重复元素

img

二分查找找左边界#

1)针对第一种情况:

Copy
int binarySearch(vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; while (left < right) {//这是左闭右开[,),不包含最后一个数,left = right 的时候会跳出 int mid = left + ((right - left) >> 1); if (nums[mid] < targrt) left = mid + 1; else right = mid;//nums[mid] >= target, 都需要往左边收缩边界(主要) } //因为里面是没有判断left = right 这个索引的位置,需要打个补丁 return nums[left] == target ? left : -1; }

2)针对第二种情况(模板有误)

Copy

二分查找找右边界#

1)针对第一种情况

Copy
int binarySearch(vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; int mid; while (left < right) { mid = left + ((right - left) >> 1) + 1;//需要注意,这里多加了个1,这样无论是奇偶数,中间位置都偏右,这样避免了死循环(如果不加1,比如{2,2},target为2,就会死循环) if (nums[mid] > target) right = mid - 1;//收缩右边界 else left = mid;//numd[mid] <= target,都需要收缩左边界(主要) } //打个补丁,这里写左右都可以 return nums[left] == target ? left : -1; }

2)针对第二种情况

Copy

二分查找找左右边界#

分别查找左右边界即可

1)第一种情况

Copy
vector<int> searchRange(vector<int>& nums, int target) { vector<int> res{-1,-1};//res[0]存左边界,res[1]存右边界 int left = 0, right = nums.size() - 1; int mid; while (left < right) {//先找左边边界 mid = left + ((right - left) >> 1); if (nums[mid] < target) left = mid + 1; else right = mid; } res[0] = nums[left] == target ? left : -1; if (res[0] != -1) {//存在左边边界查找右边边界 if (left == nums.size() - 1 || nums[left + 1] != target) {//可能只有一个target,它的位置可能在末尾/其他位置 res[1] = left; } else {//有多个target right = nums.size() - 1; while (left < right) { mid = left + ((right - left) >> 1) + 1; if (nums[mid] > target) right = mid - 1; else left = mid; } res[1] = nums[left] == target ? left : -1; } } return res; }

模板三:二分查找找极值点#

二分查找的一种变式:找极值,即是v或者^的最值点;

我们查找的时候不再是和target进行比较,而是和相邻元素比较,以达到某种单调区间检测的效果

下面以查找^的极值点写一个模板:

Copy
int binarySearch(vector<int>& nums) { int left = 0, right = nums.size() - 1; int mid; while (left <= right) { mid = left + ((right - left) >> 1); if (nums[mid] > nums[mid] + 1 && nums[mid] > nums[mid - 1]) return mid; else if (nums[mid] > nums[mid + 1]) right = mid - 1;//极值点在左边 else left = mid + 1;//极值点在右边 } return -1; }
posted @   D-booker  阅读(150)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示
CONTENTS