Welcome to Subscribe On Youtube
Question
Formatted question description: https://leetcode.ca/all/81.html
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?
Algorithm
In the previous problem “Search in Rotated Sorted Array,” there were no repeated values, so we could follow the rule that if the number in the middle is less than the rightmost number, the right half is ordered, and if the number is greater than the rightmost number, the left half is ordered.
However, if there are repeated values, there are two situations to consider: [3 1 1]
and [1 1 3 1]
. In these situations, when the middle value is equal to the rightmost value, the target value 3 could be either on the left or on the right.
If the target value is on the right, we simply move the rightmost value to the left and continue the loop. If it is still the same, we continue to move until we reach a different value. After that, we can use the same method as in “Search in Rotated Sorted Array” to find the target value.
Code
-
public class Search_in_Rotated_Sorted_Array_II { // time: O(1) // space: O(N) public class Solution { public boolean search(int[] nums, int target) { if (nums == null || nums.length == 0) { return false; } int i = 0; // left pointer int j = nums.length - 1; // right pointer while(i <= j) { int mid = (i + j) / 2; if (nums[mid] == target) { return true; } // @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; } else { i++; } } else { // right half ordered, left half not ordered // if (target <= nums[mid]) { if (nums[mid] <= target && target <= nums[j]) { i = mid; } else { j--; } } } return false; } } } ############ 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] == target) return true; if (nums[mid] < nums[r] || nums[mid] < nums[l]) { if (target > nums[mid] && target <= nums[r]) l = mid + 1; else r = mid - 1; } else if (nums[mid] > nums[l] || nums[mid] > nums[r]) { if (target < nums[mid] && target >= nums[l]) r = mid - 1; else l = mid + 1; } else r--; } return false; } }
-
// OJ: https://leetcode.com/problems/search-in-rotated-sorted-array-ii/ // Time: average O(logN), worst O(N) // Space: O(1) class Solution { int findStart(vector<int> &A) { int L = 0, R = A.size() - 1; while (L + 1 < R) { if (A[L] < A[R]) return L; int M = (L + R) / 2; if (A[M] > A[R]) L = M + 1; else if (A[M] < A[R] || (A[M] == A[R] && A[L] > A[R])) R = M; else { int k = L; while (k < R && A[L] == A[k]) ++k; if (k == R) return L; if (A[k] < A[L]) return k; L = k + 1; } } return A[L] < A[R] ? L : R; } public: bool search(vector<int>& A, int T) { if (A.empty()) return false; int start = findStart(A), N = A.size(), L = 0, R = N - 1; while (L <= R) { int M = (L + R) / 2, mid = (start + M) % N; if (A[mid] == T) return true; if (A[mid] < T) L = M + 1; else R = M - 1; } return false; } };
-
class Solution: def search(self, nums: List[int], target: int) -> bool: if not nums: return False i = 0 # left pointer j = len(nums) - 1 # right pointer while i <= j: mid = (i + j) // 2 if nums[mid] == target: return True if nums[i] <= nums[mid]: # left half ordered, right half not ordered if nums[i] <= target <= nums[mid]: j = mid else: i += 1 else: # right half ordered, left half not ordered if nums[mid] <= target <= nums[j]: i = mid else: j -= 1 return False ############ class Solution: # OJ passed def search(self, nums: List[int], target: int) -> bool: l, r = 0, len(nums) - 1 while l <= r: mid = (l + r) >> 1 if nums[mid] == target: return True if nums[mid] < nums[r] or nums[mid] < nums[l]: if target > nums[mid] and target <= nums[r]: l = mid + 1 else: r = mid - 1 elif nums[mid] > nums[l] or nums[mid] > nums[r]: if target < nums[mid] and target >= nums[l]: r = mid - 1 else: l = mid + 1 else: r -= 1 return False
-
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 }
-
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; }