2021年02月04日 周四 天气晴 【不悲叹过去,不荒废现在,不惧怕未来】
1. 题目简介
2. 题解
2.1 lower_bound 结合 upper_bound
lower_bound(): 返回 第一个大于或等于target 的元素位置,都小于的话返回 end()
upper_bound(): 返回 第一个大于target 的元素位置,都小于或等于的话返回 end()
class Solution {
public:
int search(vector<int>& nums, int target) {
vector<int>::iterator it_beg = lower_bound(nums.begin(),nums.end(),target);
// target不存在的情况
if(it_beg==nums.end() || *it_beg != target) return 0;
// 因为上面已经判断过target不存在的情况,所以这里要么返回end(),要么返回第一个
// 大于target的元素位置,这两种情况可以合并
vector<int>::iterator it_end = upper_bound(nums.begin(),nums.end(),target);
// 返回最终结果
return it_end - it_beg;
}
};
2.2 手撸 lower_bound()、upper_bound()
这里就是二分查找的变形,手撸 lower_bound()、upper_bound()。
下面是代码,细节一共有4处,建议背下来,免得面试的时候一紧张而忘记到底该不该 =,该写成 -1 还是加 +1。
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.empty()) return 0;
int idx_beg = 0, idx_end = 0;
int n = nums.size();
// 返回 第一个等于target 的元素位置(类似lower_bound,稍有改动),都不等于的话返回 0
int l = 0, r = n - 1; // 细节1:r = n - 1
while(l < r){
// 细节2:l < r
int m = l + (r - l)/2;
// 细节3:三种情况分开写,便于理解
if(nums[m] < target) l = m + 1;
else if(nums[m] == target) r = m;
else r = m - 1;
}
// 细节4:l == r 的情况单独判断
if(nums[l]==target) idx_beg = l;
else return 0;
// 返回 第一个大于target 的元素位置(类似upper_bound,稍有改动),都小于等于的话
// 返回最后的索引+1(其实就是对应end())
l = 0, r = n - 1; // 细节1:r = n - 1
while(l < r){
// 细节2:l < r
int m = l + (r - l)/2;
// 细节3:三种情况分开写,便于理解
if(nums[m] < target) l = m + 1;
else if(nums[m] == target) l = m + 1;
else r = m;
}
// 细节4:l == r 的情况单独判断
// 如果这里等于,那么就都小于等于target,返回最后的索引+1(对应end())
if(nums[l]==target) idx_end = l + 1;
// 否则,返回第一个大于target的元素位置
else idx_end = l;
return idx_end - idx_beg;
}
};
参考文献
《剑指offer 第二版》
https://www.cnblogs.com/mxj961116/p/11945444.html