标签:right target nums int Offer mid 53 查找 边界
统计一个数字在排序数组中出现的次数。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: 0
思路:利用两次二分找到重复数字区间的左边界和右边界,相减就是重复数字的个数。
代码来源:https://leetcode-cn.com/u/brando-2/
//利用两次二分法分别确定target的左右边界(左右边界为target值序列的左/右一位,因此最终结果是right-left-1)
class Solution {
public int search(int[] nums, int target) {
if(nums.length == 0) {
return 0;
}
//初始左右指针位置
int i = 0;
int j = nums.length-1;
//第一次二分:找right边界
//这边是“小于等于”,因此当循环结束后,ij不重合,且如果存在target值的话,i的位置就是右边界(target值序列右边第一个大于target值的位置),因为最后一次循环一定是i=mid+1;且此时j指向target
while(i <= j) {
int mid = (i+j) >> 1;
//这里是“小于等于”,目的是为了确定右边界,就是说当mid等于target时,因为不确定后面还有没有target,所以同样需要左边收缩范围
if(nums[mid] <= target){
i = mid+1;
}
else{
j = mid-1;
}
}
//在更新right边界值之前,需要判断这个数组中是否存在target,如果不存在(看j指向的位置是不是target,为什么看的是j指针?详见上面的注释)
if(j>=0&&nums[j] != target){
return 0;
}
int right = i; //更新right边界
//重置指针
i = 0;
j = nums.length-1;
//第二次二分:找left边界
//结束之后,j指向target序列左边第一个小于它的位置,i指向target(经过上面判断,target一定存在)
while(i <= j) {
int mid = (i+j) >> 1;
//这里是“大于等于”,目的是确定左边界,因为就算当mid等于target的时候,因为不确定左边还有没有target,所以同样需要收缩右边界
if(nums[mid] >= target){
j = mid-1;
}
else{
i= mid+1;
}
}
//更新左指针
int left = j;
return right-left-1;
}
}
参考:https://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof
标签:right,target,nums,int,Offer,mid,53,查找,边界 来源: https://blog.csdn.net/weixin_45840409/article/details/118654607
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。