剑指Offer-11 旋转数组的最小数

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。

示例 1:

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

输入:[2,2,2,0,1]
输出:0

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof

解题思路

分情况讨论

  1. 如果整个数组是递增的, 则首元素小于尾元素, 此时直接返回第一个元素
  2. 整个数组不是递增的, 用二分法
    1. 设置三个索引, 分别是最左、最右、中间
    2. 循环判断
      1. 如果"左边的数小于等于中间的数", 则说明左边到中间这区间的数是递增的, 最小数不在这里, 将左索引赋值为中间索引
      2. 如果"右边的数大于等于中间的数", 则说明中间到右边这区间的数是递增的, 最小数不在这里, 将右索引赋值为中间索引
    3. 但是要注意一个特殊情况, 如果"左边的数 == 中间的数 == 右边的数", 此时无法判断最小数所在区间, 只能顺序遍历

代码

class Solution {
    public int minArray(int[] numbers) {
        if (numbers == null || numbers.length == 0) {
            return 0;
        }
        int length = numbers.length;
        int left = 0, right = length - 1, mid;
        // 检查左边的数是否大于等于右边的数
        while (numbers[left] >= numbers[right]) {
            // 如果两个索引相邻, 则最小数一定在右边
            if (right - left == 1) {
                return numbers[right];
            }
            mid = (left + right) / 2;
            // 当左索引的数和右索引的数和中间索引的数相等
            // 此时无法知道最小数位于哪个半区, 只能顺序查找
            if (numbers[left] == numbers[right] && numbers[left] == numbers[mid]) {
                return minInOrder(numbers, left, right);
            }
            // 如果左边的数比中间小, 则说明left到mid的区间的数是递增的
            // 所以最小数不在这个范围, 将范围缩小(左索引赋值为中间)
            if (numbers[left] <= numbers[mid]) {
                left = mid;
            }
            // 同理, 右边的数大于中间, 则mid到right的区间的数是递增的
            // 最小数不在这个范围内, 将范围缩小(右索引赋值为中间)
            else if (numbers[right] >= numbers[mid]) {
                right = mid;
            }
        }
        // 根本没进去循环, 说明整个数组是递增的
        return numbers[0];
    }

    // 顺序查找的方法
    public int minInOrder(int[] nums, int left, int right) {
        // 现将结果设定为第一个数
        int result = nums[left];
        for (int i = left + 1; i <= right; i++) {
            // 找到第一个比result小的数就赋值然后返回
            if (result > nums[i]) {
                result = nums[i];
                break;
            }
        }
        return result;
    }
}

你可能感兴趣的:(二分法,数据结构)