二分查找算法
二分查找
题目描述:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
来源:LeetCode 704
面试:暂无(太简单啦 😄)
class Solution {
public:
int search(vector<int>& nums, int target) {
int size = nums.size();
int lhs = 0, rhs = size-1; //区间大小为[0,size-1]左闭右闭
while(lhs<=rhs) //左闭右闭区间,循环中止条件为lhs==rhs+1,否则会漏掉lhs==rhs的情况。
//如果是左闭右开区间[lhs,rhs)那么,lhs==rhs时可能会越界,循环中止条件为lhs==rhs,即while(lhs<rhs)
{
int mid = lhs+(rhs-lhs)/2; //这种写法避免越界,一定要写道循环体内部才行
if(nums[mid]>target) rhs = mid-1;
else if(nums[mid]<target) lhs = mid+1;
else if(nums[mid]==target) return mid;
}
return -1;
}
};
在排序数组中查找数字
题目描述:统计一个数字在排序数组中出现的次数。
来源:剑指offer 53-I && LeetCode 34
面试公司:暂无
思路:二分查找
易错点:判断数组是否越界!!!!很重要!!
返回一个值
可以使用STL的upper_bound和lower_bound
class Solution {
public:
int search(vector<int>& nums, int target) {
return upper_bound(nums.begin(),nums.end(),target)-lower_bound(nums.begin(),nums.end(),target);
}
};
返回一个范围
class Solution {
public:
vector<int> search(vector<int>& nums, int target) {
vector<int> res;
int start = left_bound(nums,target);
int end = right_bound(nums.target);
res.push_back(start);
res.push_back(end);
return res;
}
int left_bound(vector<int>& nums, int target) {
int size = nums.size();
int lhs = 0, rhs = size-1;
while(lhs<=rhs){
int mid = lhs+(rhs-lhs)/2;
if(nums[mid]>target) rhs = mid-1;
else if(nums[mid]<target) lhs = mid+1;
else if(nums[mid]==target) rhs = mid-1; //往左端逼近,所以修改右侧
}
//检查越界,当target为最大值时,lhs==rhs+1会越界
if(lhs>=size || nums[lhs]!=target) //细节,判断数组是否越界要放在最前面!!!
return -1;
return left;
}
int right_bound(vector<int>& nums, int target) {
int size = nums.size();
int lhs = 0, rhs = size-1;
while(lhs<=rhs){
int mid = lhs+(rhs-lhs)/2;
if(nums[mid]>target) rhs = mid-1;
else if(nums[mid]<target) lhs = mid+1;
else if(nums[mid]==target) lhs = mid+1; //往右端逼近,所以修改左侧
}
if(rhs<0 || nums[rhs]!=target) //细节,判断数组是否越界要放在最前面!!!
return -1;
return rhs;
}
};