154. Find Minimum in Rotated Sorted Array II***

​https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/​

题目描述

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., ​​[0,1,2,4,5,6,7]​​​ might become ​​[4,5,6,7,0,1,2]​​).

Find the minimum element.

The array may contain duplicates.

Example 1:

Input: [1,3,5]
Output: 1

Example 2:

Input: [2,2,2,0,1]
Output: 0

Note:

解题思路

和 ​​153. Find Minimum in Rotated Sorted Array**​​ 区别是: 原数组中有重复元素了.

思路 1: 来自 LeetCode 的讨论区: ​​My pretty simple code to solve it​​​, 和 ​​nums[hi]​​ 比较, 直接看实现吧.

思路 2: 我的思路, 从数组末尾开始, 将等于 ​​nums[0]​​​ 的元素全部忽略, 然后使用 ​​153. Find Minimum in Rotated Sorted Array**​​​ 的二分法, 找第一个小于 ​​nums[0]​​ 的结果.

C++ 实现 1

实现思路 1.

When ​​num[mid] == num[hi]​​, we couldn’t sure the position of minimum in mid’s left or right, so just let upper bound reduce one.

注意实现细节, ​​nums[mid]​​​ 是和 ​​nums[hi]​​ 进行比较:

  • ​nums[mid] > nums[hi]​​​, 说明此时可以将​​lo = mid + 1​​​, 因为​​mid​​ 此时指向数值较大的部分数组;
  • ​nums[mid] < nums[hi]​​​, 此时可以将​​hi = mid​​​, 因为此时​​mid​​​ 指向的是数值较小的部分数组, 此时将​​hi​​​ 直接指向​​mid​​ 即可;
  • ​nums[mid] == nums[hi]​​​, 说明此时数组末尾存在重复值, 此时将​​hi --​​, 尽量略过这些值.
class Solution {
public:
int findMin(vector<int> &num) {
int lo = 0;
int hi = num.size() - 1;
int mid = 0;

while(lo < hi) {
mid = lo + (hi - lo) / 2;
if (num[mid] > num[hi]) {
lo = mid + 1;
}
else if (num[mid] < num[hi]) {
hi = mid;
}
else { // when num[mid] and num[hi] are same
hi--;
}
}
return num[lo];
}
};

C++ 实现 2

使用 ​​153. Find Minimum in Rotated Sorted Array**​​​ 中的代码和思路, 但是有一些需要改变的地方, 主要在于处理如下情况: ​​[10, 1, 10, 10, 10]​​​, 如果直接使用 153 题的代码, 最后的结果是 10 而不是 1, 这是因为, 153 题中的代码首先确认的 mid 在 1 的索引后面(即 ​​nums[mid]​​​ 等于 10), 那么之后代码就会在 1 后面的大量 10 中查找第一个小于 10 的元素, 但很明显, 这是不存在的, 此时 ​​l​​​ 越界, 最后会返回 ​​nums[0]​​.

为了处理这种情况, 可以使用 ​​while (nums[r] == nums[0]) r--​​; 将右边的索引拉到第一个小于 10 的元素上来, 然后再进行搜索即可(可以直接用 153 题的代码了).

class Solution {
public:
int findMin(vector<int>& nums) {

int l = 0, r = nums.size() - 1;
// 只增加如下一行代码即可解决问题.
while (nums[r] == nums[0]) r --;
while (l <= r) {
int mid = l + (r - l) / 2;
if (nums[mid] >= nums[0])
l = mid + 1;
else
r = mid - 1;
}
return l >= nums.size() ? nums[0] : nums[l];
}
};