81. Search in Rotated Sorted Array II
Description
There is an integer array nums
sorted in non-decreasing order (not necessarily with distinct values).
Before being passed to your function, nums
is rotated at an unknown pivot index k
(0 <= k < nums.length
) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]
(0-indexed). For example, [0,1,2,4,4,4,5,6,6,7]
might be rotated at pivot index 5
and become [4,5,6,6,7,0,1,2,4,4]
.
Given the array nums
after the rotation and an integer target
, return true
if target
is in nums
, or false
if it is not in nums
.
You must decrease the overall operation steps as much as possible.
Example 1:
Input: nums = [2,5,6,0,0,1,2], target = 0 Output: true
Example 2:
Input: nums = [2,5,6,0,0,1,2], target = 3 Output: false
Constraints:
1 <= nums.length <= 5000
-104 <= nums[i] <= 104
nums
is guaranteed to be rotated at some pivot.-104 <= target <= 104
Follow up: This problem is similar to Search in Rotated Sorted Array, but nums
may contain duplicates. Would this affect the runtime complexity? How and why?
Solutions
Solution 1: Binary Search
We define the left boundary of the binary search as $l = 0$ and the right boundary as $r = n - 1$, where $n$ is the length of the array.
Each time during the binary search, we get the current midpoint $\textit{mid} = (l + r) / 2$.
If $\textit{nums}[\textit{mid}] > \textit{nums}[r]$, it means $[l, \textit{mid}]$ is ordered. If $\textit{nums}[l] \le \textit{target} \le \textit{nums}[\textit{mid}]$, it means $\textit{target}$ is in $[l, \textit{mid}]$. Otherwise, $\textit{target}$ is in $[\textit{mid} + 1, r]$.
If $\textit{nums}[\textit{mid}] < \textit{nums}[r]$, it means $[\textit{mid} + 1, r]$ is ordered. If $\textit{nums}[\textit{mid}] < \textit{target} \le \textit{nums}[r]$, it means $\textit{target}$ is in $[\textit{mid} + 1, r]$. Otherwise, $\textit{target}$ is in $[l, \textit{mid}]$.
If $\textit{nums}[\textit{mid}] = \textit{nums}[r]$, it means the elements $\textit{nums}[\textit{mid}]$ and $\textit{nums}[r]$ are equal. In this case, we cannot determine which interval $\textit{target}$ is in, so we can only decrease $r$ by $1$.
After the binary search, if $\textit{nums}[l] = \textit{target}$, it means the target value $\textit{target}$ exists in the array. Otherwise, it does not exist.
The time complexity is $O(n)$, where $n$ is the length of the array. The space complexity is $O(1)$.
Python3
class Solution:
def search(self, nums: List[int], target: int) -> bool:
n = len(nums)
l, r = 0, n - 1
while l < r:
mid = (l + r) >> 1
if nums[mid] > nums[r]:
if nums[l] <= target <= nums[mid]:
r = mid
else:
l = mid + 1
elif nums[mid] < nums[r]:
if nums[mid] < target <= nums[r]:
l = mid + 1
else:
r = mid
else:
r -= 1
return nums[l] == target
Java
class Solution {
public boolean search(int[] nums, int target) {
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (nums[mid] > nums[r]) {
if (nums[l] <= target && target <= nums[mid]) {
r = mid;
} else {
l = mid + 1;
}
} else if (nums[mid] < nums[r]) {
if (nums[mid] < target && target <= nums[r]) {
l = mid + 1;
} else {
r = mid;
}
} else {
--r;
}
}
return nums[l] == target;
}
}
C++
class Solution {
public:
bool search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (nums[mid] > nums[r]) {
if (nums[l] <= target && target <= nums[mid]) {
r = mid;
} else {
l = mid + 1;
}
} else if (nums[mid] < nums[r]) {
if (nums[mid] < target && target <= nums[r]) {
l = mid + 1;
} else {
r = mid;
}
} else {
--r;
}
}
return nums[l] == target;
}
};
Go
func search(nums []int, target int) bool {
l, r := 0, len(nums)-1
for l < r {
mid := (l + r) >> 1
if nums[mid] > nums[r] {
if nums[l] <= target && target <= nums[mid] {
r = mid
} else {
l = mid + 1
}
} else if nums[mid] < nums[r] {
if nums[mid] < target && target <= nums[r] {
l = mid + 1
} else {
r = mid
}
} else {
r--
}
}
return nums[l] == target
}
TypeScript
function search(nums: number[], target: number): boolean {
let [l, r] = [0, nums.length - 1];
while (l < r) {
const mid = (l + r) >> 1;
if (nums[mid] > nums[r]) {
if (nums[l] <= target && target <= nums[mid]) {
r = mid;
} else {
l = mid + 1;
}
} else if (nums[mid] < nums[r]) {
if (nums[mid] < target && target <= nums[r]) {
l = mid + 1;
} else {
r = mid;
}
} else {
--r;
}
}
return nums[l] === target;
}
Rust
impl Solution {
pub fn search(nums: Vec<i32>, target: i32) -> bool {
let (mut l, mut r) = (0, nums.len() - 1);
while l < r {
let mid = (l + r) >> 1;
if nums[mid] > nums[r] {
if nums[l] <= target && target <= nums[mid] {
r = mid;
} else {
l = mid + 1;
}
} else if nums[mid] < nums[r] {
if nums[mid] < target && target <= nums[r] {
l = mid + 1;
} else {
r = mid;
}
} else {
r -= 1;
}
}
nums[l] == target
}
}
JavaScript
/**
* @param {number[]} nums
* @param {number} target
* @return {boolean}
*/
var search = function (nums, target) {
let [l, r] = [0, nums.length - 1];
while (l < r) {
const mid = (l + r) >> 1;
if (nums[mid] > nums[r]) {
if (nums[l] <= target && target <= nums[mid]) {
r = mid;
} else {
l = mid + 1;
}
} else if (nums[mid] < nums[r]) {
if (nums[mid] < target && target <= nums[r]) {
l = mid + 1;
} else {
r = mid;
}
} else {
--r;
}
}
return nums[l] === target;
};