【剑指offer】旋转数组的最小数字

来源:互联网 发布:金字塔软件使用说明书 编辑:程序博客网 时间:2024/06/15 17:46

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组 { 3, 4, 5, 1, 2 } 为 { 1, 2, 3, 4, 5 } 的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。


package test.test;/** * 递增数组的旋转数组 如:{1, 2, 3, 4, 5}的旋转数组之一是{3, 4, 5, 1, 2} * 即:将 123 三个数旋转到末尾,此时数组是两个递增数组 345 和 12 ,前面数组的值都会大于后面数组的值。 * 最小值就是两个数组的分界值,也是后面较小数组的第一个值。此时可以利用类似二分法来查找 * min是首位,max是末位,mid = (min + max) / 2 * 若 array[mid] > array[min] 则说明  mid 位处于前半组较大的数组内,分界值在mid位后,所以令min = mid; * 若 array[mid] < array[min] 则说明  mid 位处于后半组较小的数组内,分界值在mid位前,所以令max = mid; * 按此赋值,min 始终位于前面较大数组内,max 始终位于后面较小数组内 * 直到min是较大数组的最后一位,同时max为较小数组第一位,此时他们相差1, 最小值就是max位所在值。 *  * 当 min mid max 三个位置的值都相等时, 比如:{1,0,1,1,1} 和 {1,1, 1,0,1} * 此时无法判断分界值0到底处于前半段还是后半段,因此此时只能暴力查找了。 *  */public class TestMinNumberInRotateArray {    // array为一递增数组的旋转数组 如:{3,4,5,1,2}    public int minNumberInRotateArray(int[] array) {        int min = 0;        int max = array.length - 1;        int mid = min;        while (array[min] >= array[max]) {            if (max - min == 1) {                mid = max;                break;            }            mid = (min + max) / 2;            // 若前中后三个位置的大小一致,则无法判断分界值在前半段还是后半段,只能暴力搜索了。            if (array[min] == array[mid] && array[max] == array[mid]) {                for (int i = min; i < max; i++) {                    if (array[i] > array[i+1]) {                        return array[i+1];                    }                }            }            if (array[mid] >= array[max]) {                min = mid;            } else if (array[mid] < array[max]) {                max = mid;            }        }        return array[max];    }    public static void main(String[] args) {        System.out.println(new TestMinNumberInRotateArray().minNumberInRotateArray(new int[] { 1, 1, 1, 1, 0 }));    }}