【剑指 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

解题思路1

排序取最小元素 调用api 不推荐

代码

class Solution {
    public int minArray(int[] numbers) {
        Arrays.sort(numbers);
        return numbers[0];
    }
}

在这里插入图片描述

解题思路2

二分查找,不断缩减区间。分治思想。
题目要求旋转数组,其实有可能是2个递增区间
情况1:
例如【3,4,5,1,2】 的【3,4,5】和【1,2】
l指向3 r指向2,取中间索引指向5
我们以中间索引指向的值和r指向的值进行比较:5>2,于是我们一定能确定最小值一定不在【3,4,5】这个区间中,缩减区间只留下【1,2】
在此判断1<2 在此缩短区间留下1为最小值。

情况2:
例如【1,1,1,2,2,2】
l指向最左边的1 r指向最右边的2 取中间索引指向1
我们以中间索引指向的值和r指向的值进行比较:1<2 于是我们一定能确定最小值不在【2,2,2】区间中,缩减区间留下【1,1,1】
在这个区间中 1=1 所以我们在此缩短区间将最右边的1抛出也是不影响结果的 留下区间【1,1】同理1=1 留下区间【1】
找到最小值

代码

class Solution {
    public int minArray(int[] numbers) {
        //判空操作
        if(numbers.length==0){
            return 0;
        }
        //left指针指向数组第一个元素
        int l = 0;
        //right指针指向数组最后一个元素
        int r = numbers.length - 1;
        //退出条件,左右指针重合
        while (l < r) {
            int mid = l+((r-l)>>1);
            //上述例子情况2
            //下一轮搜索区间[l,mid]
            if (numbers[mid] < numbers[r]) {
                r = mid;
            } 
            //上述例子情况1
             //下一轮搜索区间是 [mid+ 1, r]
            else if (numbers[mid] > numbers[r]) {
                l = mid + 1;
            } 
            //上述例子情况2
            //下一轮搜索区间是 [l, r- 1]
            else if (numbers[mid] == numbers[r]) {
                r = r - 1;
            }
        }
        return numbers[l];
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_35416214/article/details/107426468