【复习1】 二分查找
【使用labuladong的算法小抄进行复习】
二分查找的思路并不复杂,但是算法实现的细节十分重要,区间是否开闭、大于小于号是否取等,如果没有理解这些细节,每次写二分查找只能靠菩萨保佑才能没有bug。
所有的二分查找基于以下框架
int binarySearch(int[] nums,int[] target) { int left = 0,right = ...; while(...) { int mid = left + (right - left) / 2; //防止left+right溢出 if(nums[mid]==target) { ... } else if(nums[mid] < target) { left =... } else if(nums[mid] > target) { right = ... } } return ...; }
对于二分茶渣进行一步细分。
二分查找常见的有三种场景:寻找一个数、寻找左侧边界、寻找右侧边界。
一、寻找一个数
搜索一个数,如果存在,返回其索引,如果不存在,返回-1
int binarySearch(int[] nums, int target) { int left = 0; int right = nums.length -1 ;//表示在[left,right]左右两端闭区间里面进行搜索 while(left <= right){ //当搜索区间为空时需要退出循环 //当left=right时,搜索区间并不为空,不用推出循环 int mid = left + (right - left)/2; if(nums[mid] == target) { return mid; } else if(nums[mid] < target) { left = mid + 1; //由于mid已经搜索过,需要从搜索区间中剔除 } else if(nums[mid] > targe) { right = mid - 1; } } }
二、寻找左侧边界的二分搜索
如果存在多个重复数字的情况,需要查找最靠左端的target
或者数组中不存在target,寻找一个接近target的最左边界。
int left_bound(int[] nums,int target) { int left = 0; int right = nums.length; while(left < right) { mid = (left + right)/2; if(nums[mid] == target) { right = mid } else if(nums[mid] < target) { left = mid + 1; } else if(nums[mid] > target) { right = mid; } } return left; }
三、寻找右侧边界的二分查找
int right_bound(int[] nums,int target) { if(nums.length == 0)return -1; int left = 0; int right = nums.length; while(left < right) { mid = (left+right)/2; if(nums[mid] == target) { left = mid + 1; } else if(nums[mid] < target) { left = mid + 1; } else if(nums[mid] > target) { right = mid; } } return left - 1; }