闭区间二分搜索的边界

闭区间二分搜索 #

二分搜索根据区间的开闭一般有三种写法:左开右闭、左闭右开、闭区间。

熟悉其中一种就够了,下面是闭区间的二分搜索:

int lower_bound(vector<int>& nums, int target){
    // 区间为[0, nums.siz()-1],闭区间
    int left=0, right=nums.size()-1;	
    // 当 left<=right 不成立时,[left, right]为空区间,退出循环
   	while(left <= right){	
        // 目标在右侧时,更新左区间
        if(nums[mid] < target)
            left = mid + 1;
        // 目标在左侧时,更新右区间
        else if(nums[mid] > target)
            right = mid - 1;
        // 当找到目标值时,持续更新左区间
        else
            right = mid - 1;
    }
    return left;	// 返回左边界
}

需要了解这个算法在不同条件下的返回值:

  • 当target在数组中存在时,返回它的左边界;

  • 当target小于所有元素时,返回的左边界为0;

  • 当target大于所有元素时,返回的左边界为nums.size();

  • 当上述情况都不满足时,返回大于target的最小元素的左边界!!!(这和第二条相符)

总结来说,这个算法返回的是大于等于target的最小元素的左边界!!!

根据上面的规则,假如要查找一个有序数组中重复元素的左右边界,可以采用如下方式:

int left = 0, right = 0;
left = lower_bound(nums, target);
if(nums[left] == target)	// 数组中存在该元素
	right = lower_bound(nums, target+1)-1;
else:
	printf("不存在该元素")

要计算该元素在数组中出现的次数,可以直接采用right - left + 1的方式。

这是比较考验微操的算法,得多熟悉一下。

leetcode相关题目: 2529. 正整数和负整数的最大计数 | 275. H 指数 II

comments powered by Disqus