33.搜索旋转排序数组;153.寻找旋转排序数组中的最小值 4. 寻找两个正序数组的中位数
33.搜索旋转排序数组
思路:
- 二分查找的实现要求数组是单调有序的;现在虽然整个数组不是单调有序的,但由于其是在单调有序的数组上进行旋转得到,因此我们可以对其进行分割来得到两个单调有序的子数组。
- 对这两个单调有序的子数组进行二分查找就可以实现O(logn)的时间复杂度查询。
- 故关键在于如何划分得到这两个单调有序的子数组
方法:
- 通过判断判断middle, left 的相对大小,来判断当前哪段区间是单调有序。
- 判断target是否在这个单调有序区间内,如果在则继续对这个区间进行缩进。如果不在则在另外一个区间进行判断,继续重复上述操作。直到找到可能含有target的区间,并在该区间内进行查找
Code
class Solution:def search(self, nums: List[int], target: int) -> int:### 二分查找; 时间复杂度:O(log n)## 思路, 虽然整个数组不是单调有序的,但对该数组进行切分可以得到两个有序的数组,对这两个有序的数组进行二分查找即可。## 故关键在于如何分割得到这两个有序数组left, right = 0, len(nums)-1while left <= right:middle = left + (right-left) // 2if nums[middle] == target:return middleif nums[left] <= nums[middle]: ### left 到 middle这段区间是单调有序的if nums[left] <= target < nums[middle]: ### target在这段区间内right = middle - 1 #### 对这段区间进行二分查找else:left = middle + 1 ### 不在这段区间else: ### left 到 middle这段区间不是单调有序的;而middle到right这段区间是单调有序的if nums[middle] < target <= nums[right]:left = middle + 1else:right = middle - 1return -1 ### 找不到### 暴力解决# if target in nums: ### 时间复杂度:O(n)# return nums.index(target)# else:# return -1
153.寻找旋转排序数组中的最小值
思路
- 通过判断判断middle, left 的相对大小,来判断当前哪段区间是单调有序。
- 知道某段区间是单调有序后,其实这段区间的最小值也就知道了,然后更新下最小值。
- 随后判断另一个区间是否有更小的值。
- 判断最小值的逻辑是中 - 左/右
Code
class Solution:def findMin(self, nums: List[int]) -> int:left, right = 0, len(nums)-1min_value = float('inf')while left <= right:middle = left + (right-left)//2min_value = min(min_value, nums[middle])if nums[left] <= nums[middle]: ### 该区间单调 [left:middle+1]; 那此时最小值就是nums[left]了,你需要做的是判断右边区间的最小值min_value = min(min_value, nums[left])left = middle + 1else: ### 该区间单调 [middle: right+1]; 那此时最小值就是nums[right]了,你需要做的是判断左边区间的最小值min_value = min(min_value, nums[right])right = middle - 1return min_value
4. 寻找两个正序数组的中位数
思路
Code