public int search(int[] nums, int target) { int l = 0; int r = nums.length - 1; while (l <= r) { int m = l + (r - l) / 2; if (nums[m] == target) { return m; } if (nums[l] <= nums[m]) { // l..m is sorted if (target < nums[l] || target > nums[m]) { l = m + 1; } else { r = m - 1; } } else { // m..r is sorted if (target < nums[m] || target > nums[r]) { r = m - 1; } else { l = m + 1; } } } return -1;}
- l
- —
- r
- —
- m
- —
- nums[m]
- —
- sorted half
- —
Why it works
- Brute force scans every value: O(n). Another route finds the rotation point first (153) and then runs a plain binary search on the correct piece: still O(log n), but two passes.
- Key insight: one half is always sorted. Cut
[l, r]atmand at most one side contains the drop. Comparenums[l]withnums[m]to see which side is clean. A sorted run has known bounds, so one range check says whethertargetcan be inside it. If yes, keep it; if no, keep the other side. - O(log n) time, O(1) space. Every probe discards half of
[l, r], exactly as in plain binary search; only the rule for picking the half changed. - Pitfall:
<=innums[l] <= nums[m]. Whenl == m(two cells left) the left "half" is the single cellm, which is sorted. With<,[3, 1]and target 1 picks the wrong side and returns -1. - Follow-up: with duplicates (81),
nums[l] == nums[m]hides which side is sorted. Steplforward by one and retry; the worst case becomes O(n).