剑指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];
    }

    //顺序查找最小值
    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;
    }

}

猜你喜欢

转载自blog.csdn.net/m0_37862405/article/details/80099801