30-Day Leetcoding Challenge Day19
本题主要用二分法的思想。因为题目要求时间复杂度为O(logn)。
1.首先用二分法找到旋转点,将数组分为两个递增子序列,再分别对两个子数组用二分法找到目标值。
2.再传统的二分法基础上多加一次判断,判断当前序列是否为递增序列。
JAVA
class Solution { int []nums; int target; public int rotated(int left, int right){ if(nums[left] < nums[right])return 0; while(left <= right){ int pivot = (left+right)/2; if(nums[pivot] > nums[pivot+1])return pivot+1; if(nums[left] > nums[pivot]) right = pivot-1; else left = pivot+1; } return 0;//bug要写返回值 } public int search(int left, int right){ while(left <= right){ int mid = (left+right)/2; if(nums[mid] == target) return mid; else{ if(nums[mid] > target)right = mid-1; else left = mid+1; } } return -1; } public int search(int[] nums, int target) { this.nums = nums; this.target = target; int n = nums.length; if(n == 0)return -1; if(n == 1){ if(nums[0] == target)return 0; else return -1; } int ro_index = rotated(0, n-1); if(ro_index == 0)return search(0, n-1); if(nums[0] > target)return search(ro_index, n-1); else return search(0, ro_index-1); } }
class Solution { public int search(int[] nums, int target) { int n = nums.length; int left = 0; int right = n-1; while(left <= right){ int mid = (left+right)/2; if(nums[mid] == target)return mid; if(nums[mid] >= nums[left]){ if(nums[mid] >= target && nums[left] <= target){ right = mid-1; } else left = mid+1; } else{ if(nums[mid] <= target && nums[right] >= target){ left = mid+1; } else right = mid-1; } } return -1; } }
Python3
class Solution: def search(self, nums: List[int], target: int) -> int: def rotated(left, right): if nums[left] < nums[right]: return 0 while left <= right: pivot = (left+right)//2 if nums[pivot] > nums[pivot+1]:#二分法判定旋转点 return pivot+1 else: if nums[pivot] >= nums[left]: left = pivot+1 else: right = pivot-1 def search(left, right): while left <= right: mid = (left+right)//2 if nums[mid] == target: #二分法判定找到目标值 return mid else: if nums[mid] > target: right = mid-1 else: left = mid+1 return -1 n = len(nums) if n == 0: return -1 if n == 1: return 0 if nums[0] == target else -1 ro_index = rotated(0, n-1) #找到旋转点 if ro_index == 0: #数组有序 return search(0, n-1) if target < nums[0]: #在右边有序数组中 return search(ro_index, n-1) else: #在左边有序数组中 return search(0, ro_index-1)
class Solution: def search(self, nums: List[int], target: int) -> int: n = len(nums) left = 0 right = n-1 while left <= right: mid = (left+right)//2 if nums[mid] == target: return mid if nums[mid] >= nums[left]: if nums[left] <= target <= nums[mid]: right = mid-1 else: left = mid+1 else: if nums[mid] <= target <= nums[right]: left = mid+1 else: right = mid-1 return -1