注:排序数组的查找问题首先考虑使用 二分法 解决,其可以将遍历法的线性级别时间复杂度降低到 对数级别
1. 找到第一个大于K的元素
nums = [5,7,7,8,8,9,10,10]
target =8
left,right = 0,len(nums)-1
while(left<=right):
mid = left+(right-left)//2
if nums[mid]<=target:
left = mid+1
elif nums[mid]>target:
right = mid-1
left
2. 找到最后一个 ≤k的元素
nums = [5,7,7,8,8,9,10,10]
target =8
left,right = 0,len(nums)-1
while(left<=right):
mid = left+(right-left)//2
if nums[mid]<=target:
left = mid+1
elif nums[mid]>target:
right = mid-1
right
3. 找到第一个≥k的元素
nums = [5,7,7,8,8,9,10,10]
target =8
left,right = 0,len(nums)-1
while(left<=right):
mid = left+(right-left)//2
if nums[mid]<target:
left = mid+1
elif nums[mid]>=target:
right = mid-1
left
4. 找到最后一个小于k的元素
nums = [5,7,7,8,8,9,10,10]
target =8
left,right = 0,len(nums)-1
while(left<=right):
mid = left+(right-left)//2
if nums[mid]<target:
left = mid+1
elif nums[mid]>=target:
right = mid-1
right
一、在有序数组中找到 数字K出现的次数
第一种解法:
1. 找到最后一个 小于k 的数字的坐标 l ;
2. 找到第一个 大于k 的数字的坐标 r ;
3. 则 数字k的个数为:r-l-1
第二种解法:
1. 找到 第一个大于k的元素r
2. 找到第一个大于k-1的元素l
3. 则k的个数为 r-l
class Solution:
def search(self, nums: List[int], target: int) -> int:
def searchleft(target):
left,right = 0,len(nums)-1
while(left<=right):
mid = left+(right-left)//2
if nums[mid]<=target:
left = mid+1
elif nums[mid]>target:
right = mid-1
return right
l = searchleft(target-1)
r = searchleft(target)
return r-l
二、旋转数组的最小数字
1. 变成一个二分查找问题
2. 判断numbers[mid] 和numbers[r] 的关系
如果 numbers[mid] > numbers[r] : 则最小值一定在 [mid+1,j]区间内
如果 numbers[mid] < numbers[r] : 则最小值一定在 [l,mid]区间内
如果 numbers[mid] == numbers[r] : 则最小值无法判断在那个区间,直接缩小 j 的范围 ,令 j = j-1
class Solution:
def minArray(self, numbers: List[int]) -> int:
if len(numbers)==0:
return
if len(numbers)==1:
return numbers[0]
l,r = 0,len(numbers)-1
while(l<r):
mid = l + (r-l)//2
if numbers[mid]>numbers[r]:
l = mid+1
elif numbers[mid]<numbers[r]:
r = mid
else:
r-=1
return numbers[l]