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

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 }

LeetCode 题目总结

原文地址:https://www.cnblogs.com/cnoodle/p/11795870.html