Difficulty: Medium · LeetCode 33
Problem
Given array nums rotated at an unknown pivot and integer target, return index of target or -1 in $O(\log n)$ time.
Understanding the problem
At least one half of the array (left or right) is guaranteed to be strictly sorted at any step.
Intuition
Check if nums[left] <= nums[mid]. If True, left half is sorted: check if target is inside [nums[left], nums[mid]). Else right half is sorted: check if target is inside (nums[mid], nums[right]].
Approach
Set
left = 0,right = len(nums) - 1.Loop while
left <= right:If
nums[mid] == target, returnmid.If
nums[left] <= nums[mid](Left half sorted):If
nums[left] <= target < nums[mid], moveright = mid - 1; elseleft = mid + 1.Else (Right half sorted):
If
nums[mid] < target <= nums[right], moveleft = mid + 1; elseright = mid - 1.
Naive Solution — Brute Force
Linear scan checking each element.
class Solution:
def search(self, nums, target):
for i, num in enumerate(nums):
if num == target:
return i
return -1class Solution {
public:
int search(vector<int>& nums, int target) {
for (int i = 0; i < nums.size(); i++) {
if (nums[i] == target) {
return i;
}
}
return -1;
}
};class Solution {
public int search(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
if (nums[i] == target) {
return i;
}
}
return -1;
}
}var search = function(nums, target) {
for (let i = 0; i < nums.length; i++) {
if (nums[i] === target) {
return i;
}
}
return -1;
};Time: O(n) · Space: O(1)
Optimized Code (Python 3)
class Solution:
def search(self, nums, target):
left = 0
right = len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
# Left half is sorted
if nums[left] <= nums[mid]:
if nums[left] <= target < nums[mid]:
right = mid - 1
else:
left = mid + 1
# Right half is sorted
else:
if nums[mid] < target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return -1class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
}
// Left half is sorted
if (nums[left] <= nums[mid]) {
if (nums[left] <= target && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
// Right half is sorted
else {
if (nums[mid] < target && target <= nums[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
};class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
}
// Left half is sorted
if (nums[left] <= nums[mid]) {
if (nums[left] <= target && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
// Right half is sorted
else {
if (nums[mid] < target && target <= nums[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
}var search = function(nums, target) {
let left = 0;
let right = nums.length - 1;
while (left <= right) {
const mid = left + Math.floor((right - left) / 2);
if (nums[mid] === target) {
return mid;
}
// Left half is sorted
if (nums[left] <= nums[mid]) {
if (nums[left] <= target && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
// Right half is sorted
else {
if (nums[mid] < target && target <= nums[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
};Time: O(log n) · Space: O(1)
Takeaway
Pattern — Rotated array → Identify sorted half → Binary search boundary