33. Search in Rotated Sorted Array
题目描述
在旋转的已经排好序的数组中寻找目标值target
分析
方法一:
特殊情况,数组为空返回-1
while循环寻找target,二分法:
(检查target在当前low,mid,high的哪个范围,更新边界)
1.若low和mid都在未旋转区域
1.判断target是否在low-mid之间,若是,更新右边界high;
2.否则,更新左边界low
2.其他情况:
1.判断target是否在mid-high之间,若是,更新左边界low;
2.否则,更新右边界high
若之前无返回,即未找到,返回-1
完整代码
class Solution: def search(self, nums, target): """ :type nums: List[int] :type target: int :rtype: int """ if not nums: #特殊情况:数组为空 return -1 low, high = 0, len(nums) - 1 while low <= high: #循环条件 mid = (low + high) // 2 if target == nums[mid]: #找到目标 return mid #low和mid都在未旋转区域 if nums[low] <= nums[mid]: #若target在low和mid之间,更新右端点 if nums[low] <= target <= nums[mid]: high = mid - 1 #若target不在low和mid之间,更新左端点 else: low = mid + 1 #若nums[low] > nums[mid],即low在未旋转区域,mid在旋转区域 else: #若target在mid和high之间,更新左端点 if nums[mid] <= target <= nums[high]: low = mid + 1 else: high = mid - 1 return -1 #之前未返回结果,则未找到,返回-1
分析
方法二:
1. 利用二分法,寻找nums数组中最小值的索引MinIdx:
当nums[mid]>nums[right]时,更新left=mid+1;其余情况,right=mid
2. 比较target与nums末尾元素的大小关系,限定欲搜索数组的始末位置:
target>nums末尾元素: target 位于数组的前半部分(未旋转区域),start=0,end=MinIdx-1
target<nums末尾元素: target 位于数组的后半部分(旋转区域),start=MinIdx,end=数组末尾
3. 使用二分法在nums[start:end]中搜索target
完整代码
public int search(int[] nums, int target) { int minIdx = findMinIdx(nums); if (target == nums[minIdx]) return minIdx; int m = nums.length; int start = (target <= nums[m - 1]) ? minIdx : 0; int end = (target > nums[m - 1]) ? minIdx : m - 1; while (start <= end) { int mid = start + (end - start) / 2; if (nums[mid] == target) return mid; else if (target > nums[mid]) start = mid + 1; else end = mid - 1; } return -1; } public int findMinIdx(int[] nums) { int start = 0, end = nums.length - 1; while (start < end) { int mid = start + (end - start) / 2; if (nums[mid] > nums[end]) start = mid + 1; else end = mid; } return start; }