Welcome to Subscribe On Youtube
Question
Formatted question description: https://leetcode.ca/all/33.html
33. Search in Rotated Sorted Array
Level
Medium
Description
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,1,2,4,5,6,7]
might become [4,5,6,7,0,1,2]
).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
Your algorithm’s runtime complexity must be in the order of O(log n).
Example 1:
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
Example 2:
Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1
Solution
To solve the problem in O(log n) runtime complexity, use binary search. Since the sorted array is rotated at some pivot, the logic is a little different from traditional binary search.
Use two pointers low
and high
, which initially point to the begin and the end of the array respectively. The loop condition is low <= high
. Each time choose mid
as the average of low
and high
. If nums[mid] == target
, then return mid
. Otherwise, decide which half should be searched next, [low, mid - 1]
or [mid + 1, high]
. Two cases may exist. The first case is that nums[low] <= nums[mid]
, which means the rotation point is on the right of mid
. Search in [low, mid - 1]
if target
is between nums[low]
and nums[mid]
, and otherwise search in [mid + 1, high]
. The first case is that nums[low] > nums[mid]
, which means the rotation pointer is on the left of mid
. Search in [mid + 1, high]
if target
is between nums[mid]
and nums[high]
, and otherwise search in [low, mid - 1]
. If target
is not found, return -1
.
Code
-
public class Search_in_Rotated_Sorted_Array { // time: O(1) // space: O(N) public class Solution { public int search(int[] nums, int target) { if (nums == null || nums.length == 0) { return -1; } int i = 0; // left pointer int j = nums.length - 1; // right pointer while (i <= j) { int mid = (i + j) / 2; // @note: possible overflow, use: int mid = i + (j - i) / 2 if (nums[mid] == target) { return mid; } /* @note: I missed case when nums[mid] is the max of the values, then both mid-left-half and mid-right-half are ordered: array=[3,5,1], target=1 array=[3,5,1], target=3 array=[4,5,6, 7, 1,2,3] @note: question is, how to deal with case where mid-value is max-value? initially I was thinking compare mid with mid-1 value and mid+1 value, but tedious simple solution is, add another condition to make a range query: nums[i] < target and target < nums[mid] */ // @note: if (nums[0] <= nums[mid]) { if (nums[i] <= nums[mid]) { // left half ordered, right half not ordered // if (target <= nums[mid]) { if (nums[i] <= target && target <= nums[mid]) { j = mid - 1; } else { // i++; //[NOT binary] i = mid + 1; } } else { // right half ordered, left half not ordered // if (target <= nums[mid]) { if (nums[mid] <= target && target <= nums[j]) { i = mid + 1; } else { // j--; //[NOT binary] j = mid - 1; } } } return -1; } } } ############ class Solution { public int search(int[] nums, int target) { int n = nums.length; int left = 0, right = n - 1; while (left < right) { int mid = (left + right) >> 1; if (nums[0] <= nums[mid]) { if (nums[0] <= target && target <= nums[mid]) { right = mid; } else { left = mid + 1; } } else { if (nums[mid] < target && target <= nums[n - 1]) { left = mid + 1; } else { right = mid; } } } return nums[left] == target ? left : -1; } }
-
// OJ: https://leetcode.com/problems/search-in-rotated-sorted-array/ // Time: O(logN) // Space: O(1) class Solution { public: int search(vector<int>& nums, int target) { if (nums.empty()) return -1; int L = 0, R = nums.size() - 1, pivot; while (L < R) { int M = L + (R - L) / 2; if (nums[M] < nums[R]) R = M; else L = M + 1; } pivot = L; if (pivot && target >= nums[0] && target <= nums[pivot - 1]) L = 0, R = pivot - 1; else L = pivot, R = nums.size() - 1; while (L <= R) { int M = L + (R - L) / 2; if (nums[M] == target) return M; if (target > nums[M]) L = M + 1; else R = M - 1; } return -1; } };
-
# below 2 solutions, diff is while condition: left ('<' or '<=') right # I like this better class Solution: def search(self, nums: List[int], target: int) -> int: n = len(nums) left, right = 0, n - 1 while left <= right: mid = (left + right) >> 1 if nums[mid] == target: return mid elif nums[0] <= nums[mid]: # left half sorted if nums[0] <= target <= nums[mid]: right = mid - 1 else: left = mid + 1 else: # right half sorted if nums[mid] < target <= nums[n - 1]: left = mid + 1 else: right = mid -1 return -1 ############ class Solution: def search(self, nums: List[int], target: int) -> int: n = len(nums) left, right = 0, n - 1 while left < right: mid = (left + right) >> 1 if nums[0] <= nums[mid]: # left half sorted if nums[0] <= target <= nums[mid]: right = mid else: left = mid + 1 else: # right half sorted if nums[mid] < target <= nums[n - 1]: left = mid + 1 else: right = mid return left if nums[left] == target else -1
-
func search(nums []int, target int) int { n := len(nums) left, right := 0, n-1 for left < right { mid := (left + right) >> 1 if nums[0] <= nums[mid] { if nums[0] <= target && target <= nums[mid] { right = mid } else { left = mid + 1 } } else { if nums[mid] < target && target <= nums[n-1] { left = mid + 1 } else { right = mid } } } if nums[left] == target { return left } return -1 }
-
function search(nums: number[], target: number): number { const n = nums.length; let left = 0, right = n - 1; while (left < right) { const mid = (left + right) >> 1; if (nums[0] <= nums[mid]) { if (nums[0] <= target && target <= nums[mid]) { right = mid; } else { left = mid + 1; } } else { if (nums[mid] < target && target <= nums[n - 1]) { left = mid + 1; } else { right = mid; } } } return nums[left] == target ? left : -1; }
-
/** * @param {number[]} nums * @param {number} target * @return {number} */ var search = function (nums, target) { const n = nums.length; let left = 0, right = n - 1; while (left < right) { const mid = (left + right) >> 1; if (nums[0] <= nums[mid]) { if (nums[0] <= target && target <= nums[mid]) { right = mid; } else { left = mid + 1; } } else { if (nums[mid] < target && target <= nums[n - 1]) { left = mid + 1; } else { right = mid; } } } return nums[left] == target ? left : -1; };
-
impl Solution { pub fn search(nums: Vec<i32>, target: i32) -> i32 { let mut l = 0; let mut r = nums.len() - 1; while l <= r { let mid = l + r >> 1; if nums[mid] == target { return mid as i32; } if nums[l] <= nums[mid] { if target < nums[mid] && target >= nums[l] { r = mid - 1; } else { l = mid + 1; } } else { if target > nums[mid] && target <= nums[r] { l = mid + 1; } else { r = mid - 1; } } } -1 } }