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
.
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 is a follow up problem to Search in Rotated Sorted Array, where
nums
may contain duplicates. - Would this affect the run-time complexity? How and why?
在旋转有序数组中搜索二。
这题跟33题求的一样,多一个条件是input里面有重复数字。依然是用二分法做,但是worst case很可能会到O(n);而且其中一开始需要多一个case的判断,就是 nums[mid] 和 nums[start] ,nums[end] 的大小关系。因为在重复数字的数量超过数组一半的情况下,nums[mid] 和 nums[start] ,nums[end] 有可能都是相等的,此时需要将左右指针都分别往中间靠近,排除重复元素之后再判断。
时间O(logn), worst case O(n)
空间O(1)
JavaScript实现
1 /** 2 * @param {number[]} nums 3 * @param {number} target 4 * @return {boolean} 5 */ 6 var search = function(nums, target) { 7 // corner case 8 if (nums === null || nums.length === 0) { 9 return false; 10 } 11 12 // normal case 13 let start = 0; 14 let end = nums.length - 1; 15 while (start + 1 < end) { 16 let mid = Math.floor(start + (end - start) / 2); 17 if (nums[mid] === target) return true; 18 if (nums[start] === nums[mid] && nums[mid] === nums[end]) { 19 start++; 20 end--; 21 } else if (nums[start] <= nums[mid]) { 22 if (nums[start] <= target && target <= nums[mid]) { 23 end = mid; 24 } else { 25 start = mid; 26 } 27 } else if (nums[mid] <= nums[end]) { 28 if (nums[mid] <= target && target <= nums[end]) { 29 start = mid; 30 } else { 31 end = mid; 32 } 33 } 34 } 35 if (nums[start] === target) return true; 36 if (nums[end] === target) return true; 37 return false; 38 };
Java实现一,while (start + 1 < end)
1 class Solution { 2 public boolean search(int[] nums, int target) { 3 // corner case 4 if (nums == null || nums.length == 0) { 5 return false; 6 } 7 8 // normal case 9 int start = 0; 10 int end = nums.length - 1; 11 while (start + 1 < end) { 12 int mid = start + (end - start) / 2; 13 if (nums[mid] == target) { 14 return true; 15 } 16 if (nums[start] == nums[mid] && nums[mid] == nums[end]) { 17 start++; 18 end--; 19 } else if (nums[start] <= nums[mid]) { 20 if (nums[start] <= target && target <= nums[mid]) { 21 end = mid; 22 } else { 23 start = mid; 24 } 25 } else if (nums[mid] <= nums[end]) { 26 if (nums[mid] <= target && target <= nums[end]) { 27 start = mid; 28 } else { 29 end = mid; 30 } 31 } 32 } 33 if (nums[start] == target) { 34 return true; 35 } 36 if (nums[end] == target) { 37 return true; 38 } 39 return false; 40 } 41 }
Java实现二,while (start <= end)
1 class Solution { 2 public boolean search(int[] nums, int target) { 3 int start = 0; 4 int end = nums.length - 1; 5 // start <= end最后跳出while循环的时候end < start 6 // end和start是邻近的两个index,所以无需特判 7 while (start <= end) { 8 int mid = start + (end - start) / 2; 9 if (nums[mid] == target) { 10 return true; 11 } 12 // 缩减重复元素的部分 13 if (nums[start] == nums[mid] && nums[mid] == nums[end]) { 14 start++; 15 end--; 16 } 17 // target在左半段 18 else if (nums[start] <= nums[mid]) { 19 if (nums[start] <= target && target <= nums[mid]) { 20 end = mid - 1; 21 } else { 22 start = mid + 1; 23 } 24 } 25 // target在右半段 26 else if (nums[mid] <= nums[end]) { 27 if (nums[mid] <= target && target <= nums[end]) { 28 start = mid + 1; 29 } else { 30 end = mid - 1; 31 } 32 } 33 } 34 return false; 35 } 36 }