前言
本专栏文章为《代码随想录》书籍的刷题题解以及读书笔记,如有侵权,立即删除。
二分查找有一般有两种写法,主要思想是利用搜索区间的定义来确定代码条件:
[left,right]
(左闭右闭)left
和right
的值都可以取到,而且left
和right
的值可以相等。所以:
left=0
、right=nums.size()-1
。left<=right
nums[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()
。left
nums[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);
。