剑指Offer-题11(Java版):旋转数组的最小数字

参考自:《剑指Offer——名企面试官精讲典型编程题》

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

主要思路:旋转后的数组分成两个排序的子数组,前面的子数组都大于或等于后面的子数组,最小元素就是两个子数组的分界线。因此,使用两个指针(左指针和右指针)分别指向第一个元素和最后一个元素,接着找到数组的中间元素((左指针+右指针)/2),判断其与两个指针指向元素的大小。
分三种情况:
1.若中间元素大于或等于左指针指向的元素:说明中间元素位于前面的非递减子数组,最小元素应该位于该中间元素的后面,因此把左指针指向中间元素,缩小查找范围。
2.若中间元素小于或等于右指针指向的元素:说明中间元素位于后面的非递减子数组,最小元素应该位于该中间元素的前面,因此把右指针指向中间元素,缩小查找范围。
1和2情况中要移动指针,直到左指针指向前面子数组的最后一个元素,右指针指向后面子数组的第一个元素(该元素即为最小值)。

3.若中间元素同时等于左指针和右指针指向的元素,则只能按顺序查找。

关键点:数组部分有序,缩小查找范围,二分查找

时间复杂度:O(logn)

public class MinNumberInRotateArray {
    public static void main(String[] args) {
        int[] array1 = {3, 4, 5, 1, 2};
        int[] array4 = {1, 0, 1, 1, 1};
        System.out.println(findMinNumberInArray(array1));
        System.out.println(findMinNumberInArray(array4));
    }

    private static int findMinNumberInArray(int[] array) {
        if (array == null || array.length <= 0) {
            return -1;
        }
        //左指针
        int leftIndex = 0;
        int rightIndex = array.length - 1;
        int midIndex = leftIndex;
        while (array[leftIndex] >= array[rightIndex]) {
            //左右指针相邻,找到最小值
            if (rightIndex - leftIndex == 1) {
                midIndex = rightIndex;
                break;
            }
            midIndex = (leftIndex + rightIndex) / 2;
            //前中后三个值相等,则顺序查找
            if ((array[leftIndex] == array[rightIndex])
                    && (array[leftIndex] == array[midIndex])) {
                return minInOrder(array, leftIndex, rightIndex);
            }
            //中间值大于或等于左指针指向元素(前半段还是非递减),则最小值在后半段
            if (array[midIndex] >= array[leftIndex]) {
                leftIndex = midIndex;
            }
            //中间值小于或等于右指针指向元素(后半段还是非递减),则最小值在前半段
            else if (array[midIndex] <= array[rightIndex]) {
                rightIndex = midIndex;
            }
        }
        return array[midIndex];
    }

    /**
     * 顺序查找最小值
     *
     * @param array       the array
     * @param aheadIndex  the ahead index
     * @param behindIndex the behind index
     * @return the int
     */
    private static int minInOrder(int[] array, int aheadIndex, int behindIndex) {
        int result = array[aheadIndex];
        for (int i = aheadIndex + 1; i <= behindIndex; i++) {
            if (result > array[i]) {
                result = array[i];
            }
        }
        return result;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值