统计一个数字在排序数组中出现的次数()。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: 0
限制:
0 <= 数组长度 <= 50000
思路一:
这个思路也是最容易想到的,从左边开始遍历找到第一个出现的,位置用
表示;从右开始遍历找到第一个出现的
,位置用
表示,那么
在排序数组中出现的次数为
。这种方法的时间复杂度O(n),空间复杂度O(1)。
代码:
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
i = 0
j = len(nums)-1
while i <= j and nums[i] != target:
i+=1
while j >= 0 and nums[j] != target :
j-=1
if i > j:
return 0
else:
return j-i+1
思路二:
采用二分法的思想来做,下面我们给出二分法的步骤:
初始化: 左边界
,右边界
。
循环二分: 当,即闭区间无元素时跳出;
计算中点(向下取整);
若,则
在闭区间
中,因此执行
;
若,则
在闭区间
中,因此执行
;
若,则返回m,退出循环。
思路:
排序数组
中的所有数字
形成一个窗口,记窗口的 左 / 右边界 索引分别为
和
,分别对应窗口左边 / 右边的首个元素。
本题要求统计数字
的出现次数,可转化为:使用二分法分别找到 左边界
和 右边界
,易得数字
的数量为
。
具体步骤:
初始化: 左边界
,右边界
。
循环二分: 当,即闭区间无元素时跳出;
计算中点(向下取整);
若,则
在闭区间
中,因此执行
;
若,则
在闭区间
中,因此执行
;
若,则右边界
在闭区间
中;左边界
在闭区间
中。因此分为 以下两种情况:
(1)若查找 右边界,则执行
;(跳出时
指向右边界)
(2)若查找 左边界,则执行
;(跳出时
指向左边界)
复杂度分析:
- 时间复杂度 O(log N): 二分法为对数级别复杂度。
- 空间复杂度 O(1): 几个变量使用常数大小的额外空间。
代码:
class Solution:
def search(self, nums: [int], target: int) -> int:
# 搜索右边界 right
i, j = 0, len(nums) - 1
while i <= j:
m = (i + j) // 2
if nums[m] <= target: i = m + 1
else: j = m - 1
right = i
# 若数组中无 target ,则提前返回
if j >= 0 and nums[j] != target: return 0
# 搜索左边界 left
i = 0
while i <= j:
m = (i + j) // 2
if nums[m] < target: i = m + 1
else: j = m - 1
left = j
return right - left - 1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof