[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 }

 

LeetCode 题目总结

posted @ 2019-11-05 00:03  CNoodle  阅读(423)  评论(0编辑  收藏  举报