二分查找
二分查找模板
class Solution {
public:
int search(vector<int>& nums, int target) {
int low=0;
int high = nums.size()-1;
while(low<=high){
int mid = low +(high - low)/2;
if(nums[mid] == target){
return mid;
}
else if(nums[mid]<target){
low = mid + 1;
}
else{
high = mid -1;
}
}
return -1;
}
};
这个是二分查找的模板,有关二分查找的题都在这个模板上删减而来。
第一题解思路
第一题就是简单的二分查找,直接用模板
第二题解思路
第一个错误的版本,即要找到有重复数组中对应值的最左边界,实际上还是二分查找问题。只需要在模板中注意,数组起始为1结束为n(而非其实为0结束为n-1)。
while中取low<high,不取等号。此时跳出while循环的条件就是low == high。可以对取不取等号做简单理解,取low<=high时,跳出循环时high在左边而low在右边,(比如3 5,查找4,最后一定是high指向3,low指向5,方便后续操作);取low<high时,跳出循环时high=low,假设二分查找未找到,high=low的情况low和high可能指向前一个位置也可能指向后一个位置(比如3 5,查找4,low和high可能同时指向3,也可能同时指向5),不好确定位置。
在nums[mid]找到 target时,将右边界置为此mid(不需要-1,因为此时nums[mid]为T,是潜在的解,不能因为判断过就跳过)。
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
int low = 1;
int high = n;
while(low<high){
int mid = low+(high-low)/2;
if(isBadVersion(mid)){
high = mid;
}else{
low = mid + 1;
}
}
return low;
}
};
第三题解思路
二分插入问题,取模板,low=0,high = n-1,毋庸置疑
while中应该取low<=high,因为这样,二分查找没找到时,low指向该空位的下一个,而high指向该空位的上一个,找位置插入一定是插在该空位的下一个位置,(比如3 5 ,插入4,二分查找取等号,未找到时low一定指向5而high一定指向3,我们应该在3 5之间插入4即在空位之后(5的位置)插入),也就是说是插在low指向的位置。
每次更新low后保存,如果未找到(表现为跳出while循环)即在low的位置插入即可。
注意初始res设置为0,是因为nums中最小数都比target大的时候,在第0位置插入。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int low = 0;
int high = nums.size()-1;
int res = 0;
while(low<=high){
int mid = low + (high - low)/2;
if(nums[mid] == target){
return mid;
}else if(nums[mid] < target){
low = mid + 1;
res = low;
}else{
high = mid - 1;
}
}
return res;
}
};