剑指Offer 面试题08:旋转数组的最小数字

旋转数组的最小数字

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

解题思路

先处理两种特殊情况。搜索范围头元素小于搜索范围尾元素,直接得出结果。搜索范围头元素、中间元素、尾元素相等,退化为顺序查找。然后根据搜索范围的头元素与中间元素的大小关系,缩小搜索范围。缩小到搜索范围只剩1到2个元素时得出结果。缩小搜索范围的核心思想是二分法。

代码

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        // 处理特殊值
        if (array == null) {
            return 0;
        }
        if (array.length == 0) {
            return 0;
        }
        
        // 初始化数组搜索范围
        int arrayLength = array.length;
        int firstIndex = 0;
        int lastIndex = arrayLength - 1;
        
        while (lastIndex - firstIndex > 0) {
            int firstValue = array[firstIndex];
            int lastValue = array[lastIndex];
            
            // 搜索范围剩余1个或2个元素时,直接得出结果
            if (lastIndex == firstIndex) {
                return firstValue;
            } else if (lastIndex - firstIndex == 1) {
                if (firstValue < lastValue) {
                    return firstValue;
                } else {
                    return lastValue;
                }
            }
            
            int middleIndex = (firstIndex + lastIndex) / 2;
            int middleValue = array[middleIndex];
            if (firstValue < lastValue) {
                // 搜索范围头元素小于搜索范围尾元素,直接得出结果
                return firstValue;
            } else if (firstValue == lastValue && firstValue == middleValue) {
                // 搜索范围头元素、中间元素、尾元素相等,退化为顺序查找
                return minNumberInRotateArrayBySequenceSearch(array);
            }
            
            // 根据搜索范围的头元素与中间元素的大小关系,缩小搜索范围
            if (middleValue < firstValue) {
                lastIndex = middleIndex;
            } else {
                firstIndex = middleIndex;
            }
        }
        // 不会执行到这里
        return 0;
    }
    
    // 顺序查找数组中的最小值
    private int minNumberInRotateArrayBySequenceSearch(int [] array) {
        int min = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i] < min) {
                min = array[i];
            }
        }
        return min;
    }
}