[LeetCode] 81. Search in Rotated Sorted Array II
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?
搜索旋转排序数组 II。
这题跟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 }