GuilinDev

Lc0153

05 August 2008

153 - Find Minimum in Rotated Sorted Array

原题概述

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.

You may assume no duplicate exists in the array.

Example 1:

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

Example 2:

1
2
Input: [4,5,6,7,0,1,2]
Output: 0

题意与分析

一个已经升序排好的数组以某个轴rotated调转左右的元素,然后在调转后的array里寻找到最小的元素,数组里的元素是没有重复的。这道题凭空想的话不容易想到,拿原题中的例子 [0,1,2,4,5,6,7]转变成[4,5,6,7,0,1,2]来观察规律,如果最小值如果没有rotated,为nums[0],如果rotated了,满足nums[min]<nums[min-1],也就是说最小值比它之前的数值下(index大);用Binary Search的找到中间的值nums[mid],如果找到的值小于它左边的值,则该值就是最小值 - 因为原本是升序,只有在最小值处它才会小于左边的值,直接返回;如果nums[mid]大于左边的值,那么nums[mid]有可能是[4,5,6,7,0,1,2]或[6,7,0,1,2,4,5]这样的情况,1)nums[mid]大于左边的值也大于右边的值,说明最小值在该nums[mid]右边;2)nums[mid]大于左边的值但小于右边的值,说明最小值在该nums[mid]的左边。以此类推,直到找到一个nums[mid]小于它左边的值为止。

因为数组的元素没有重复,所以跟下一道相比是简单了很多。

Time: O(logn); Space:O(1).

代码

模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
    public int findMin(int[] nums) {
        if (nums == null || nums.length == 0) {
            return Integer.MIN_VALUE;
        }
        int left = 0, right = nums.length - 1;
        if (nums[left] < nums[right]) { // 先判断是不是全局有序
            return nums[left];
        }
        // 二分法确定最小值在左边还是右边
        while (left + 1 < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > nums[left]) {
                left = mid;
            } else {
                right = mid;
            }
        }
        return Math.min(nums[left], nums[right]);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
    public int findMin(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int left = 0;
        int right = nums.length - 1;
        if (nums[left] < nums[right]) {
            return nums[left];
        }
        while (left + 1 < right) {
            int mid = left + (right - left) / 2;
            // if (mid > 0 && nums[mid] < nums[mid - 1]) {
            //     return nums[mid];
            // }
            // if (mid < nums.length - 1 && nums[mid] > nums[mid + 1]) {
            //     return nums[mid + 1];
            // }
            if (nums[mid] > nums[left]) {
                left = mid;
            } else {
                right = mid;
            }
        }
        
        // return nums[right] < nums[left] ? nums[right] : nums[left]; //模板
        return nums[right]; // left和right停在下降的地方
    }
}