[LintCode/LeetCode] Find Minimum in Rotated Sorted Array I & II

463 查看

Find Minimum in Rotated Sorted Array

Problem

Suppose a sorted array 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.

Notice

You may assume no duplicate exists in the array.

Example

Given [4, 5, 6, 7, 0, 1, 2] return 0

Note

排序数组中找最小值或最大值的题目,很明显可以使用二分法。我们先来看看rotated sorted array有哪些情况,再确定如何使用二分法:

        //LO   M   HI
        // 789123456
        // 678912345
        // 456789123
        // 123456789

上面的例子分别是较小元素,最小元素,较大元素,中位数在中点的情况。可见,用队首元素num[start]和中点num[mid]比较没有意义。因此,只判断终点和中点元素的大小关系即可。

Solution

public class Solution {
    public int findMin(int[] num) {
        int start = 0, end = num.length - 1;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (num[end] > num[mid]) end = mid;
            else start = mid;
        }
        return num[start] < num[end] ? num[start] : num[end];
    }
}


Find Minimum in Rotated Sorted Array

Problem

Suppose a sorted array 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

Given [4,4,5,6,7,0,1,2] return 0

Note

53335 x
33533 x 
55535 x
42333 x
45333 x

上面这些case是很难直接用二分法判断的,只能对中点两边同时使用二分法递归,或者完全遍历数组求最优解。
二分法递归的步骤是:建立helper()函数,当中点值大于等于末位值,夹逼到后半段,舍弃中间值;当中点值小于等于末位值,夹逼到前半段,不舍弃中间值。这里有一种情况是(上述后三个case),中点值和末位相等。此时,两边同时递归,并返回两边递归值的较小值。当首位和末位重合,说明已夹逼得到最小值。

Solution

二分法递归

public class Solution {
    public int findMin(int[] num) {
        return helper(num, 0, num.length-1);
    }
    public int helper(int[] num, int start, int end) {
        if (start == end) return num[start];
        int mid = start + (end - start) / 2;
        int left = Integer.MAX_VALUE, right = left;
        if (num[mid] >= num[end]) {
            right = helper(num, mid+1, end);
        }
        if (num[mid] <= num[end]) {
            left = helper(num, start, mid);
        }
        return Math.min(left, right);
    }
}

暴力循环

public class Solution {
    public int findMin(int[] num) {
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < num.length; i++) {
            min = Math.min(num[i], min);
        }
        return min;
    }
}