力扣每日一题 upper_bound和lower_bound解析
1.问题描述
统计一个数字在排序数组中出现的次数。
2.示例
3.问题分析
问题比较简单直接上一个二分代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int index = binarySearch(nums, target);
//cout<<index<<endl;
int count = 1;
if (index == -1) return 0;
for(int i = index + 1; i<nums.size();i++){
if(nums.at(i) == target){
count++;
}else break;
}
for(int i = index -1; i>=0; i--){
if(nums.at(i) == target){
count++;
}else break;
}
return count;
}
int binarySearch(vector<int>& nums, int target){
int left = 0, right = nums.size() - 1;
int index = 0;
while(left <= right){
int mid = left + (right - left)/2;
if(nums.at(mid) == target){
index = mid;
return index;
}
else if(nums.at(mid) > target){
right = mid - 1;
}
else if(nums.at(mid) < target){
left = mid + 1;
}
}
return -1;
}
};
这里要做笔记的是另外一种解法:
class Solution2{
public:
int search(vector<int>& nums, int target){
return upper_bound(nums.begin(),nums.end(),target) - lower_bound(nums.begin(), nums.end(),target);
}
};
详情见下标题4
另外STL暴力函数求解:
class Solution2{
public:
int search(vector<int>& nums, int target){
return count(vec.begin(), vec.end(), target);
}
}
4.upper_bound和lower_bound详解
lower_bound
和upper_bound
都是适用于对有序表的查找。底层采用的都是二分的查找方法。
4.1 lower_bound使用详解
lower_bound()
的函数原型有两种:
template <class ForwardIterator, class T>
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val);
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val, Compare comp);
函数返回一个迭代器,在所给的容器,或者数组的空间:[first, last)中寻找第一个大于等于(不小于)元素val
的元素的下标。
如果不存在这样的数,那么则返回end。注意vec的end是最后一个元素的下一个位置的指针,而不是最后一个元素。而这里所指的end对于数组则是array[size]处。
#include<algorithm>
#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
int main()
{
int array[6] = {1,4,3,9,5,6};
vector<int> vec(array, array+6); //使用数组初始化vector,遵循左闭右开原则:若写array+6则不包括array[5]
int target = 5;
int target2 = -1;
int target3 = 10;
//首先,lower_bound的使用必须是有序数组或者是容器
sort(vec.begin(),vec.end());
sort(array,array+6);
//排序后:
//array:1,3,4,5,6,9
//vec: 1,3,4,5,6,9
/****以array为例****/
//找得到的情况:
auto it = lower_bound(array,array+6,target);
printf("%d----%d\n",it-&array[0],*it); //3----5
it = lower_bound(array,array+6,target2);
printf("%d----%d\n",it-&array[0],*it); //0----1
//找不到的情况:
it = lower_bound(array,array+6,target3);
printf("%d----%d\n",it-&array[0],*it); //返回的是end,值不确定
/****以array为例****/
//找得到的情况:
auto it2 = lower_bound(vec.begin(), vec.end(), target);
printf("index = %d---- vec[index] = %d\n", it2-vec.begin(), *it2);//3----5
it2 = lower_bound(vec.begin(), vec.end(), target2);
printf("index = %d---- vec[index] = %d\n", it2-vec.begin(), *it2);//0----1
//找不到的情况:
it2 = lower_bound(vec.begin(), vec.end(), target3);
printf("index = %d---- vec[index] = %d\n", it2-vec.begin(), *it2);//返回的是end,值不确定
return 0;
}
4.2 lower_bound等价代码
template <class ForwardIterator, class T>
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator it;
iterator_traits<ForwardIterator>::difference_type count, step;
count = distance(first,last); //distance函数可以接受任意两个迭代器,计算之间的距离;这里可以理解为元素的个数
while (count>0)
{
it = first; step=count/2;
advance (it,step); //advance函数帮助的带起前进相应的步数。
if (*it<val) { // or: if (comp(*it,val)), for version (2)
first=++it;
count-=step+1;
}
else count=step;
}
return first;
}
4.3 upper_bound使用详解
upper_bound
使用方法与lower_bound
基本相同,只是upper_bound
返回的是有序序列中第一个大于target的数的迭代器,而不是第一个大于等于的数的。
#include<algorithm>
#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
int main()
{
int array[6] = {1,4,3,9,5,6};
vector<int> vec(array, array+6); //使用数组初始化vector,遵循左闭右开原则:若写array+6则不包括array[5]
int target = 5;
int target2 = -1;
int target3 = 10;
//首先,lower_bound的使用必须是有序数组或者是容器
sort(vec.begin(),vec.end());
sort(array,array+6);
//排序后:
//array:1,3,4,5,6,9
//vec: 1,3,4,5,6,9
/****以array为例****/
//找得到的情况:
auto it = upper_bound(array,array+6,target);
printf("%d----%d\n",it-&array[0],*it); //4----6
it = upper_bound(array,array+6,target2);
printf("%d----%d\n",it-&array[0],*it); //0----1
//找不到的情况:
it = upper_bound(array,array+6,target3);
printf("%d----%d\n",it-&array[0],*it); //6----1
/****以vector为例****/
//找得到的情况:
auto it2 = upper_bound(vec.begin(), vec.end(), target);
printf("index = %d---- vec[index] = %d\n", it2-vec.begin(), *it2);//4----6
it2 = upper_bound(vec.begin(), vec.end(), target2);
printf("index = %d---- vec[index] = %d\n", it2-vec.begin(), *it2);//0----1
//找不到的情况:
it2 = upper_bound(vec.begin(), vec.end(), target3);
printf("index = %d---- vec[index] = %d\n", it2-vec.begin(), *it2);//返回的是end,值不确定
return 0;
}