力扣每日一题 upper_bound和lower_bound解析

力扣每日一题 upper_bound和lower_bound解析

1.问题描述

统计一个数字在排序数组中出现的次数。

2.示例

image-20210716113753559

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_boundupper_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;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Blanche117

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值