数字在排序数组中出现的次数
统计一个数字在排序数组中出现的次数。
样例:
输入:排序数组{1,2,3,3,3,3,4,5}和数字3
输出:4
解题思路
因为是排序数组,我们首先想到用二分查找去解决问题。
核心思想就是用二分查找找到数组中的第一个k和最后一个k.
二分查找
剑指Offer上的做法,时间复杂度为
O
(
l
o
g
n
)
O(logn)
O(logn).
注意二分查先找到任意一个k再向两边遍历是属于
O
(
n
)
O(n)
O(n)的做法,毫无意义。
class Solution(object):
def getFirstK(self, nums, k):
start = 0
end = len(nums)-1
while start <= end:
mid = (start+end)//2
if nums[mid] == k:
if mid == 0 or nums[mid-1] != k:
return mid
else:
end = mid - 1
if nums[mid] < k:
start = mid + 1
if nums[mid] > k:
end = mid - 1
return -1
def getLastK(self, nums, k):
start = 0
end = len(nums)-1
while start <= end:
mid = (start+end)//2
if nums[mid] == k:
if mid == len(nums)-1 or nums[mid+1] != k:
return mid
else:
start = mid + 1
if nums[mid] < k:
start = mid + 1
if nums[mid] > k:
end = mid - 1
return -1
def getNumberOfK(self, nums, k):
"""
:type nums: list[int]
:type k: int
:rtype: int
"""
if not nums: return 0
left = self.getFirstK(nums, k)
right = self.getLastK(nums, k)
# 注意这里nums里没有k时要返回-1,若返回0在nums = [1]时会出错
return right - left + 1 if left > -1 and right > -1 else 0
二分查找改进版
不查找k的位置,而是查找k-0.5和k+0.5的位置,时间复杂度为 O ( l o g n ) O(logn) O(logn).
class Solution(object):
def binarySearch(self, nums, k):
if not nums : return
start = 0
end = len(nums) - 1
while start <= end:
mid = (start + end)//2
if nums[mid] < k:
start = mid + 1
if nums[mid] > k:
end = mid - 1
return start
def getNumberOfK(self, nums, k):
"""
:type nums: list[int]
:type k: int
:rtype: int
"""
if not nums : return 0
left = self.binarySearch(nums, k-0.5)
right = self.binarySearch(nums, k+0.5)
return right - left