题目:162. 寻找峰值 - 力扣(LeetCode)
题解: 双指针 二分查找获取目标索引。
空间复杂度:O(1)
时间复杂度:O(logn),n 为 数组nums的长度.
代码实现:
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
# 注意左右边界
left, right = -1, len(nums) - 1 # 避免边界溢出
while left + 1 < right:
mid = (left + right) // 2
if nums[mid] > nums[mid + 1]:
right = mid
else:
left = mid
return right
题目:153. 寻找旋转排序数组中的最小值
题解: 双指针,二分查找思路。
空间复杂度:O(1)
时间复杂度:O(logn), n 为nums数组的长度.
代码实现:
class Solution:
def findMin(self, nums: List[int]) -> int:
left, right = -1, len(nums) - 1
while left + 1 < right:
mid = (left + right) // 2
if nums[mid] > nums[-1]: # mid索引值和最后一个值比较 来确认区间缩减方向
left = mid
else:
right = mid
return nums[right]
题目:33. 搜索旋转排序数组 - 力扣(LeetCode)
题解:
已知:原数组,升序排序且无重复元素,分两步解题。
step1: 先获取到数组最小值对应的索引,用来划分区间。条件用:nums[mid]和nums[-1]比较俩缩小区间
step2: 原区间有序,被分割后的两个区间也是有序的,根据目标区间进行二分查找即可。
复杂度:
空间复杂度:O(1)
时间复杂度:O(logn * logn)
代码实现:
class Solution:
def search(self, nums: List[int], target: int) -> int:
index_0 = self.min_index(nums, -1, len(nums) - 1)
if target > nums[-1]:
i = self.get_target(nums, -1, index_0, target)
else:
i = self.get_target(nums, index_0 - 1, len(nums), target)
if nums[i] == target:
return i
else:
return -1
# step1: 获取最小值对应的索引下标
def min_index(self, nums: List[int], left: int, right: int) -> int:
while left + 1 < right:
mid = (left + right) // 2
if nums[mid] > nums[-1]:
left = mid
else:
right = mid
return right
# step2: 根据区间获取目标值
def get_target(self, nums: List[int], left: int, right: int, target: int) -> int:
while left + 1 < right:
mid = (left + right) // 2
if nums[mid] >= target:
right = mid
else:
left = mid
return right
题目:74. 搜索二维矩阵
题解:
遍历每行,通过判断 target 是在区间[matrix[m][0], matrix[m][-1]],如果在就进入该行进行二分查找,如果目标值为 target 直接返回 True ,否则持续遍历结束,最后 right 指针对应着潜在的目标值 target ,如果 nums[right] == target 则返回 True ,否则返回 False.
复杂度:
空间复杂度:O(1)
时间复杂度:O(m * logn), m 代表矩阵的行,n代表矩阵的列.
代码实现:
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
for mat in matrix:
if target >= mat[0] and target <= mat[len(mat) - 1]:
left, right = -1, len(mat)
while left + 1 < right:
mid = (left + right) // 2
if mat[mid] > target:
right = mid
elif mat[mid] < target:
left = mid
else:
return True
else:
continue
if mat[right] == target:
return True
else:
return False
题目:1901. 寻找峰值 II
题解:
见题解:1901. 寻找峰值 II - 力扣(LeetCode)
复杂度:
空间复杂度:O(1)
时间复杂度:O(logm), m 表示矩阵的行数.
代码实现:
class Solution:
def findPeakGrid(self, mat: List[List[int]]) -> List[int]:
left, right = -1, len(mat) - 1
while left + 1 < right:
i = (left + right) // 2
mx = max(mat[i])
if mx > mat[i + 1][mat[i].index(mx)]:
right = i
else:
left = i
return [right, mat[right].index(max(mat[right]))]
题目:154. 寻找旋转排序数组中的最小值 II
题解:
复杂度:
空间复杂度:O(1)
时间复杂度:O(logn)
代码实现:
class Solution:
def findMin(self, nums: List[int]) -> int:
left, right = -1, len(nums) - 1
while left + 1 < right:
mid = (left + right) // 2
if nums[mid] == nums[right]:
right -= 1
elif nums[mid] < nums[right]:
right = mid
else:
left = mid
return nums[right]