MediumBinary search a rotated array — one half is always still sorted.
An ascending sorted array was rotated at some unknown pivot (e.g. [0,1,2,4,5,6,7] → [4,5,6,7,0,1,2]). Given the array and a target, return the index of the target, or −1. The algorithm must run in O(log n).
Walkthrough
try:
A sorted array rotated at some pivot. Each step, one half of [lo, hi] is still sorted — use it to decide which half to keep.
0
1
2
3
4
5
6
4
5
6
7
0
1
2
lo
·
·
·
·
·
hi
target0
midsorted halfdiscardedfound
1
function search(nums, target) {
2
let lo = 0, hi = nums.length - 1;
◄
3
while (lo <= hi) {
4
const mid = (lo + hi) >> 1;
5
if (nums[mid] === target) return mid;
6
if (nums[lo] <= nums[mid]) { // left sorted
7
if (nums[lo] <= target && target < nums[mid]) hi = mid - 1;
8
else lo = mid + 1;
9
} else { // right sorted
10
if (nums[mid] < target && target <= nums[hi]) lo = mid + 1;
11
else hi = mid - 1;
12
}
13
}
14
return -1;
15
}
lo = 0hi = 6target = 0
step 0 / 8
line 2
Search window [0, 6]
Binary search still works on a rotated array — one half is always properly sorted. Look for target = 0.
Intuition
Plain binary search breaks because the array isn’t globally sorted. But here is the key observation: no matter where you cut, at least ONE half of [lo, hi] is still perfectly sorted.
Compare nums[lo] with nums[mid]: if nums[lo] ≤ nums[mid], the left half is the sorted one; otherwise the rotation lies on the left and the right half is sorted.
Inside the sorted half you can test the target with a simple range check — that half is ordinary sorted data.
If the target falls inside the sorted half, search there; otherwise it must be in the other half. Either way you throw away half the array each step → O(log n).
The algorithm
01Set lo = 0, hi = n − 1.
02Take mid; if nums[mid] is the target, return mid.
03Decide which half is sorted by comparing nums[lo] and nums[mid].
04If the target lies inside that sorted half’s range, keep it; otherwise keep the other half.
05Repeat until lo > hi, then return −1.
Reference implementation
1
function search(nums, target) {
2
let lo = 0, hi = nums.length - 1;
3
while (lo <= hi) {
4
const mid = (lo + hi) >> 1;
5
if (nums[mid] === target) return mid;
6
if (nums[lo] <= nums[mid]) { // left half sorted
7
if (nums[lo] <= target && target < nums[mid]) hi = mid - 1;
8
else lo = mid + 1;
9
} else { // right half sorted
10
if (nums[mid] < target && target <= nums[hi]) lo = mid + 1;