153. Find Minimum in Rotated Sorted Array

题目描述和难度

  • 题目描述:

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

请找出其中最小的元素。

你可以假设数组中不存在重复元素。

示例 1:

输入: [3,4,5,1,2]
输出: 1

示例 2:

输入: [4,5,6,7,0,1,2]
输出: 0

思路分析

求解关键:这道题“你可以假设数组中不存在重复元素”这个信息是关键的。

参考解答

参考解答1:二分查找算法。

public class Solution {

    public int findMin(int[] nums) {
        int len = nums.length;
        if (len == 0) {
            throw new IllegalArgumentException("数组为空");
        }
        int left = 0;
        int right = len - 1;
        // 思考,为什么是 left < right
        while (left < right) {
            // 这一步就是取中点,没有什么特别之处
            int mid = left + (right - left) / 2;

            // 特别注意:这里有个大坑,不能用 nums[left] < nums[mid]
            // 特别注意:这里有个大坑,不能用 nums[left] < nums[mid]
            // 特别注意:这里有个大坑,不能用 nums[left] < nums[mid]

            if (nums[mid] > nums[right]) {
                // 5 6 7 8 9 1 2
                // 此时可以扔掉 mid 的值
                left = mid + 1;
            } else {
                // 5 6 7 1 2 3 4
                assert nums[mid] < nums[right];
                // 此时 mid 有可能是最小值所在的索引
                right = mid;
            }
        }

        // 退出循环说明 left 与 right 相等,所以只剩一个元素可能,
        // 所以 return [left] 或者 return [right] 都可以了
        // 注意不能 return mid,可以从 {2,1} 这个输入看出来。

        return nums[right];
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums = {4, 5, 6, 7, 0, 1, 2};
        int min = solution.findMin(nums);
        System.out.println(min);
    }
}

参考解答2:使用分治的思想

/**
 * 分治的写法
 */
public class Solution2 {

    // 虽然可以通过,但是时间复杂度是 O(n)

    public int findMin(int[] nums) {
        int len = nums.length;
        if (len == 0) {
            throw new IllegalArgumentException("数组为空");
        }
        return findMin(nums, 0, len - 1);
    }

    private int findMin(int[] nums, int left, int right) {
        // 思考:这个临界条件是为什么?
        // 或者写成 left + 1 >= right
        if (left == right || left + 1 == right) {
            return Math.min(nums[left], nums[right]);
        }
        int mid = left + (right - left) / 2;
        // 8 9 1 2 3 4 5 6 7
        if (nums[mid] < nums[right]) {
            // 右边是顺序数组
            return Math.min(findMin(nums, left, mid - 1), nums[mid]);
        } else {
            // 左边是顺序数组
            // nums[mid] > nums[right]
            // 3 4 5 6 7 8 1 2
            return Math.min(nums[left], findMin(nums, mid + 1, right));
        }
    }

    public static void main(String[] args) {
        Solution2 solution2 = new Solution2();
        int[] nums = {1, 2};
        int solution2Min = solution2.findMin(nums);
        System.out.println(solution2Min);
    }

}

参考解答3:使用分治的思想

public class Solution3 {

    public int findMin(int[] nums) {
        int len = nums.length;
        if (len == 0) {
            throw new IllegalArgumentException("给出的数组为空,没有最小值");
        }
        return findMin(nums, 0, len - 1);
    }

    public int findMin(int[] nums, int left, int right) {
        // 分治的方法,首先先要处理要递归终止的条件
        if (left + 1 >= right) {
            return Math.min(nums[left], nums[right]);
        }
        if (nums[left] < nums[right]) {
            return nums[left];
        }
        int mid = left + (right - left) / 2;
        return Math.min(findMin(nums, left, mid), findMin(nums, mid + 1, right));
    }
}

本篇文章的地址为 https://liweiwei1419.github.io/leetcode-solution/leetcode-0153-find-minimum-in-rotated-sorted-array ,如果我的题解有错误,或者您有更好的解法,欢迎您告诉我 liweiwei1419@gmail.com