综合了力扣上的几种写法以及代码随想录的写法,感谢!
要点:明确区间定义,并在循环操作中保持不变(循环不变量原则)。
一、二分搜索单调数组的数(无重复)
1.左闭右闭
int binarySearch(vector<int> &nums, int target){
int left = 0, right = nums.size()-1;
while (left <= right) {
int mid = left + right >> 1;
if (nums[mid] > target) {
right = mid -1;
}
else if (nums[mid] < target) {
left = mid + 1;
}
else {
return mid;
}
}
return -1;
}
对于左闭右闭区间的写法:
1.while的判断条件是<=,在等于的条件下,区间长度为1,是有意义的。
2.left更新为mid+1,right更新为mid-1。
3.因为为右闭,所以right初值为nums.size()-1。
2.左闭右开
int binarySearch (vector<int> &nums, int target){
int left = 0, right = nums.size();
while (left < right) {
int mid = left + right >> 1;
if (nums[mid] > target) {
right = mid;
}
else if (nums[mid] < target) {
left = mid + 1;
}
else {
return mid;
}
}
return -1;
}
对左闭右开区间的写法:
1. while的判断条件是< ,因为在等于的条件下,因为区间是左闭右开,所以区间长度为0,无意义。
2.left更新为mid+1,right更新为mid(因为右边为开区间)。
若数组含有target,则返回下标,否则返回-1。
3.因为右开,所以right初值为nums.size()。
二、二分某区间的左右边界
1.左闭右闭
二分区间的右边界
int binarySearch (vector<int> &nums, int target){
int left =0, right = nums.size() - 1;
while(left <= right) {
int mid = left + right >> 1;
if (nums[mid] >= target) right = mid - 1;
else left = mid + 1;
}
return left;
}
二分后,left为大于等于target的第一个元素下标,right为最后一个小于target的元素下标。
区间的左边界为等于target的第一个元素下标,所以返回left。
二分区间的左边界:
int binarySearch (vector<int> &nums, int target){
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = left + right >> 1;
if (nums[mid] <= target) left = mid + 1;
else right = mid - 1;
}
return right;
}
二分后,right为最后一个小于等于target的元素下标,left为第一个大于target的元素下标。
区间的右边界为等于target的最后一个元素下标,所以返回right。
2.左闭右开
二分区间的左边界:
int binarySearch (vector<int> &nums, int target) {
int left = 0, right = nums.size();
while (left < right) {
int mid = left + right >> 1;
if (nums[mid] >= target) right = mid;
else right = mid + 1;
}
return right;
}
二分后,left与right相等,为第一个大于等于target的元素下标。
所以返回left和right都可以。
二分区间的右边界:
int binarySearch (vector<int> &nums, int target) {
int left = 0, right = nums.size();
while (left < right) {
int mid = left + right >> 1;
if (nums[mid] <= target) left = mid + 1;
else right = mid;
}
return right - 1;
}
二分后,left等于right,为最后一个小等等于target的元素下标+1。
所以应该返回left-1或right-1。
个人理解:二分本质上就是二分某区间的左右边界,在数组中找某个数其实也可以用二分区间的左右边界的方法。
运用二分需要数组满足单调性。
笔者水平有限,欢迎批评指正。