Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 153. Find Minimum in Rotated Sorted Array #153

Open
grandyang opened this issue May 30, 2019 · 1 comment
Open

[LeetCode] 153. Find Minimum in Rotated Sorted Array #153

grandyang opened this issue May 30, 2019 · 1 comment

Comments

@grandyang
Copy link
Owner

grandyang commented May 30, 2019

 

Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:

  • [4,5,6,7,0,1,2] if it was rotated 4 times.
  • [0,1,2,4,5,6,7] if it was rotated 7 times.

Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]].

Given the sorted rotated array nums of unique elements, return  the minimum element of this array.

You must write an algorithm that runs in O(log n) time.

 

Example 1:

Input: nums = [3,4,5,1,2]
Output: 1
Explanation: The original array was [1,2,3,4,5] rotated 3 times.

Example 2:

Input: nums = [4,5,6,7,0,1,2]
Output: 0
Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.

Example 3:

Input: nums = [11,13,15,17]
Output: 11
Explanation: The original array was [11,13,15,17] and it was rotated 4 times. 

 

Constraints:

  • n == nums.length
  • 1 <= n <= 5000
  • -5000 <= nums[i] <= 5000
  • All the integers of nums are unique.
  • nums is sorted and rotated between 1 and n times.

 

这道题说是对一个有序数组进行了若干次旋转,让找出旋转数组的最小值,这里肯定不能通过直接遍历整个数组来寻找,过于简单粗暴,这样的话,旋不旋转就没有意义。但是可以利用旋转特点来进行优化,传统的找最小值是要遍历所有的数字的,这里由于旋转前是有序的,则数组中的第一个数字是最小的,发生旋转之后,第一个数字就不一定是最小的,但是如果从第一个数字往后遍历的话,应该是递增的,但如果遇到较小的数字,则一定是转折点,大家可以自行举例验证,这种方法在极端情况下还是线性的复杂度,但只要能过 OJ 的就是好方法,曾经代码如下

 

解法一:

class Solution {
public:
    int findMin(vector<int>& nums) {
        if (nums[0] <= nums.back()) return nums[0];
        for (int num : nums) {
            if (num < nums[0]) return num;
        }
        return -1;
    }
};

 

我们可以将时间复杂度从 O(n) 缩小到 O(lgn),这时候二分查找法就浮现在脑海。这里的二分法属于博主之前的总结帖 LeetCode Binary Search Summary 二分搜索法小结 中的第五类,也是比较难的那一类,没有固定的 target 值比较,而是要跟数组中某个特定位置上的数字比较,决定接下来去哪一边继续搜索。这里用中间的值 nums[mid] 和右边界值 nums[right] 进行比较,若数组没有旋转或者旋转点在左半段的时候,中间值是一定小于右边界值的,所以要去左半边继续搜索,反之则去右半段查找,最终返回 nums[right] 即可,参见代码如下:

 

解法二:

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left = 0, right = (int)nums.size() - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > nums[right]) left = mid + 1;
            else right = mid;
        }
        return nums[right];
    }
};

 

下面这种分治法 Divide and Conquer 的解法,由热心网友 howard144 提供,这里每次将区间 [start, end] 从中间 mid 位置分为两段,分别调用递归函数,并比较返回值,每次取返回值较小的那个即可,参见代码如下:

 

解法三:

class Solution {
public:
    int findMin(vector<int>& nums) {
        return helper(nums, 0, (int)nums.size() - 1);
    }
    int helper(vector<int>& nums, int start, int end) {
        if (nums[start] <= nums[end]) return nums[start];
        int mid = (start + end) / 2;
        return min(helper(nums, start, mid), helper(nums, mid + 1, end));
    }
};

 

讨论:对于数组中有重复数字的情况,请参见博主的另一篇博文 Find Minimum in Rotated Sorted Array II

 

Github 同步地址:

#153

 

类似题目:

Search in Rotated Sorted Array

Find Minimum in Rotated Sorted Array II

 

参考资料:

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

https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/discuss/48493/Compact-and-clean-C%2B%2B-solution

https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/discuss/48484/A-concise-solution-with-proof-in-the-comment

 

LeetCode All in One 题目讲解汇总(持续更新中...)

(欢迎加入博主的知识星球,博主将及时答疑解惑,并分享刷题经验与总结,快快加入吧~)

知识星球 喜欢请点赞,疼爱请打赏❤️~.~

微信打赏

|

Venmo 打赏


---|---

@lld2006
Copy link

lld2006 commented Jun 27, 2020

和右端比很重要, 因为left < right 的情况下, mid不等于right, 要比和左边比简单的多,
mid和左边比的话, 当right = left+1的时候, mid =left。
另外 nums[mid] > nums[left] 并不能确定最小值在哪边, 有可能是left, 也有可能在另外一边。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants