左闭右闭的模版
def search(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1 # 定义target在左闭右闭的区间里,[left, right]
while left <= right:
middle = left + (right - left) // 2
if nums[middle] > target:
right = middle - 1 # target在左区间,所以[left, middle - 1]
elif nums[middle] < target:
left = middle + 1 # target在右区间,所以[middle + 1, right]
else:
return middle # 数组中找到目标值,直接返回下标
return -1 # 未找到目标值
162 寻找峰值
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
l = 0
n = len(nums)
r = len(nums) - 1
while l < r:
mid = (l + r) // 2
if mid - 1 < 0:
left = -float('inf')
else:
left = nums[mid - 1]
if mid + 1 >= n:
right = -float('inf')
else:
right = nums[mid + 1]
if nums[mid] > left and nums[mid] > right:
return mid
if right > left:
l = mid + 1
else:
r = mid
return l
153 数组向右一次移动k次后, 找min
class Solution:
def findMin(self, nums: List[int]) -> int:
# /
# /
# /
# /
# /
# /
# 三种情况, 左边, 右边, 中间
l = 0
r = len(nums) - 1
while l < r:
mid = (l + r) // 2
if nums[0] < nums[-1]: # 这个是判断是否断层了, 没断层直接nums[0]
return nums[0]
if nums[mid] >= nums[0]:
l = mid + 1
else:
r = mid
return nums[l]
153 变种, 找到target
class Solution:
def search(self, nums: List[int], target: int) -> int:
l = 0
r = len(nums) - 1 # 修改1: 改为 len(nums) - 1
while l <= r: # 修改2: 改为 <=
mid = (l + r) // 2
x = nums[mid]
if x == target:
return mid
# case1: x 和 target 都在左半部分
if x >= nums[0] and target >= nums[0]:
if x < target:
l = mid + 1
else:
r = mid - 1 # 修改3: 改为 mid - 1
# case2: x 和 target 都在右半部分
elif x < nums[0] and target < nums[0]: # 修改4: 改为 x < nums[0]
if target > x:
l = mid + 1
else:
r = mid - 1 # 修改5: 改为 mid - 1
# case3: x 和 target 在不同半部分
else:
if x < nums[0]: # x 在右半部分,target 在左半部分
r = mid - 1
else: # x 在左半部分,target 在右半部分
l = mid + 1
return -1
注意怎么分case比较好
34 排序数组中第一次出现和最后一次出现
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
def bi_right(nums, target):
l = 0
r = len(nums) - 1
while l <= r:
mid = (l + r) // 2
x = nums[mid]
if x == target:
l = mid + 1
elif x < target:
l = mid + 1
else:
r = mid - 1
return r
def bi_left(nums, target):
l = 0
r = len(nums) - 1
while l <= r:
mid = (l + r) // 2
x = nums[mid]
if x == target:
r = mid - 1
elif x < target:
l = mid + 1
else:
r = mid - 1
return l
l, r = bi_left(nums, target), bi_right(nums, target)
# 简化后的判断
if 0 <= l < len(nums) and nums[l] == target and nums[r] == target:
return [l, r]
else:
return [-1, -1]