第九周 二分
35 搜索插入位置
输入: [1,3,5,6], 5 输出: 2。
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
# 暴力法
# if nums[0]>target: return 0
# for i in range(len(nums)):
# if nums[i]==target:
# return i
# if nums[i]>target and nums[i-1]<target:
# return i
# return len(nums)
# 插入后返回idx
# if target in nums:
# return nums.index(target)
# nums.append(target)
# nums.sort()
# return nums.index(target)
# 二分法!!!
left, right=0, len(nums)
while left<right:
mid = left + (right-left)//2
if nums[mid]<target:
left = mid+1
else:
right = mid
return left
34 在排序数组中查找元素的第一个和最后一个位置
输入: nums = [5,7,7,8,8,10], target = 8 输出: [3,4]
输入: nums = [5,7,7,8,8,10], target = 6 输出: [-1,-1]
肯定得用二分法,才能时间复杂度n(logN)
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
if target not in nums: # 没有就不用遍历了
return [-1, -1]
res=[]
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
else:
res.append(mid)
left = mid+1 # 两遍,对称
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
else:
res.append(mid)
right = mid-1
res.sort() # 排序
return [res[0],res[-1]]
33 搜索旋转排序数组
class Solution:
def search(self, nums: List[int], target: int) -> int:
if target not in nums:
return -1
return nums.index(target) # 暴力查找list中target的idx
class Solution:
def search(self, nums: List[int], target: int) -> int:
if target not in nums:
return -1
# return nums.index(target)
l, r =0, len(nums)-1
while l <= r:
mid = (l+r)//2
if nums[mid]==target:
return mid
if nums[0]<=nums[mid]: # 等号没加又错了 二分法简单但是细节好容易错
if nums[0]<=target<nums[mid]:
r = mid-1
else:
l = mid+1
else:
if nums[mid]<target<=nums[len(nums)-1]:
l = mid+1
else:
r = mid-1
return -1
162 寻找峰值
输入: nums = [1,2,1,3,5,6,4] 输出: 1 或 5 。复杂度要求O(logN),想到用二分法,但一看是无序的,就不知道怎么做了。其实只要找到一个就好了,那么
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
l,r = 0, len(nums)-1
while l<r:
mid = (l+r)//2
if nums[mid]<nums[mid+1]:
l = mid+1
else:
r = mid
return l
74 搜索二维矩阵
二维矩阵的检索:row,col = mid // n,mid % n
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
m = len(matrix)
if m==0:
return False
n = len(matrix[0])
left, right = 0, m * n - 1
while left<=right:
mid = (left+right) // 2
ele = matrix[mid // n][mid % n]
if ele == target:
return True
else:
if ele>target:
right = mid - 1
else:
left = mid + 1
return False
240 搜索二维矩阵II
也是给定matrix和target,查询target是否在matrix里。但是数组横着递增,竖着递增。
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
class Solution:
def searchMatrix(self, matrix, target):
row , col = len(matrix)-1, 0 # trick:左下角,往上减小,往右增加。
if matrix == []:
return False
while row>=0 and col <= len(matrix[0])-1:
if matrix[row][col] == target:
return True
else:
if matrix[row][col]>target:
row -= 1
else:
col += 1
return False
1552 两球之间的磁力
要反向思维了奥,从答案出发二分。
class Solution:
def maxDistance(self, position: List[int], m: int) -> int:
def check(x): # 如果每隔x防止一个球,能否放够m个?能,则答案>=x
pre = position[0]
cnt = 1
for i in range(1, len(position)):
if position[i]-pre >= x:
pre = position[i]
cnt += 1
return cnt >= m
# 如果距离为3可以,那么1和2都可以,但是4+都不可以。所以可以使用二分法,答案最小1,最大max-min。
# 如果mid可以,代表[1,mid-1]都可以,答案从[mid+1, max]之间找。
position.sort()
left, right, ans = 1, position[-1]-position[0], -1
while left <= right: # 二分法标志就是这个while 不要忘记写他!
mid = (left+right)//2
if check(mid):
ans = mid
left = mid + 1
else:
right = mid -1
return ans