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
Java
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;
}
}
}