前言
本专栏文章为《代码随想录》书籍的刷题题解以及读书笔记,如有侵权,立即删除。
二分查找有一般有两种写法,主要思想是利用搜索区间的定义来确定代码条件:
[left,right](左闭右闭)left和right的值都可以取到,而且left和right的值可以相等。所以:
left=0、right=nums.size()-1。left<=rightnums[mid]>target时,更新right=mid-1。(因为根据区间定义,此时如果使right=mid,区间可以取到mid,而已知mid不满足条件,故应将区间缩小为[left,mid-1])nums[mid]时,更新为left=mid+1。(因为根据区间定义,此时如果使left=mid,区间可以取到mid,而已知mid不满足条件,故应将区间缩小为[mid+1,right]) nums[mid]==target时,返回mid。-1。[left,right)(左闭右开)left的值可以取到,而right的值取不到,而且left和right的值不可以相等。所以:
left=0、right=nums.size()。leftnums[mid]>target时,更新right=mid。(因为根据区间定义,此时如果使right=mid-1,区间取不到mid-1,会使搜索区间丢失mid-1,故应将区间缩小为[left,mid))nums[mid]时,更新left=mid+1。(因为根据区间定义,此时如果使left=mid,区间可以取到mid,而已知mid不满足条件,故应将区间缩小为[mid+1,right)) nums[mid]==target时,返回mid。-1。二分查找时间复杂度为O (log n)
左闭右闭区间定义代码
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
//防止溢出可以改为:
//int mid = left + ((right - left) / 2);
//或
//int mid = left + ((right - left) >> 1);
int mid = (left + right) / 2;
if (nums[mid] > target) right = mid - 1;
else if (nums[mid] < target) left = mid + 1;
else return mid;
}
return -1;
}
};
左闭右开区间定义代码
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size();
while (left < right) {
//防止溢出可以改为:
//int mid = left + ((right - left) / 2);
//或
//int mid = left + ((right - left) >> 1);
int mid = (left + right) / 2;
if (nums[mid] > target) right = mid;
else if (nums[mid] < target) left = mid + 1;
else return mid;
}
return -1;
}
};
mid是下标不是值,与target比较时是用nums[mid]。int mid = (left + right) / 2;改为 int mid = left + ((right - left) / 2);或int mid = left + ((right - left) >> 1);。