旋转数组的最小数字

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。

例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

题解

思路1

直接遍历

时间复杂度: O(N)- 空间复杂度: O(1)

思路2

二分查找

分析:旋转数组可以看成是两个有序数组组成的,最小元素就是这两个数组的分界点

用两个指针进行二分查找,lo指针总是指向第一个数组的终点,hi指针总是指向第二个数组的起点

直到 lo 与 hi相邻,即 lo == hi -1

时间复杂度: O(log (N))- 空间复杂度: O(1)

public int minNumberInRotateArray(int[] array) {
    if (array.length == 0)
        return 0;

    int lo = 0;
    int hi = array.length - 1;
    int m = (lo + hi) / 2;
    while (lo != hi - 1) {
        if (array[lo] <= array[m]) {
            lo = m;
            m = (lo + hi) / 2;
        }

        if (array[hi] >= array[m]) {
            hi = m;
            m = (lo + hi) / 2;
        }
    }
    return array[hi];
}

等等

这样写有缺陷

比如 {1,0,1,1,1} 和 {1,1,1,0,1} 这两个

如果中间指针 和 前后指针都相等的情况,找不出最小的

碰到这种情况只能顺序查找了

public int minNumberInRotateArray(int[] array) {
    if (array.length == 0)
        return 0;

    int lo = 0;
    int hi = array.length - 1;
    int m = (lo + hi) / 2;
    while (lo < hi - 1) {
        /*这种特殊情况,只能顺序查找*/
        if (array[lo] == array[hi] && array[lo] == array[m]) {
            int res = 0;
            for (int i = lo + 1; i < hi; i++) {
                if (res > array[i])
                    res = array[i];
            }
            return res;
        }

        if (array[lo] <= array[m]) {
            lo = m;
            m = (lo + hi) / 2;
        }

        if (array[hi] >= array[m]) {
            hi = m;
            m = (lo + hi) / 2;
        }
    }
    return array[hi];
}
全部评论

相关推荐

点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务