剑指offer面试题11(java版):旋转数组的最小数字

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/littlehaes/article/details/91384665

welcome to my blog

剑指offer面试题11(java版):旋转数组的最小数字

题目描述

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

思路

  • 见注释

复杂度

  • 时间复杂度: 因为采用的是二分查找,所以时间复杂度是O(logn)
  • 空间复杂度: O(1)
import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        // 健壮性判断
        if(array == null)
            return 0; //题目要求
        // 正式执行
        /*
        准备: 使用二分查找的思路, 设置两个指针p1,p2分别指向数组的起始和末尾, 还有一个mid指针指向p1,p2的中间位置
        1. p1永远指向第一个递增子序列中的元素, p2永远指向第二个递增子序列中的元素, 二分查找到最后:p1指向最大值, p2指向最小值
        2. 如果arr[mid] >= arr[p1] 说明mid在第一个递增子序列中, 令p1 = mid
           如果arr[mid] <= arr[p2] 说明mid在第二个递增子序列中, 令p2 = mid
           特例1:旋转了0个元素到末尾,此时arr[0]就是最小值
           特例2:arr[p1] == arr[p2] == arr[mid], 此时无法判断最小值位于哪个递增子序列中,只能用顺序查找
        */
        int p1 = 0;
        int p2 = array.length - 1;
        int mid = 0;
        // 特例1,同时也能解决数组只有1个元素的情况
        if(array[0]< array[array.length-1]) // 判断条件不能是<=
            return array[0];
        // 普通情况
        while(array[p1] >= array[p2]){ //while条件写什么好?
            if(p2-p1==1){
                mid = p2;
                break;
            }
            mid = (p1 + p2) / 2;
            if(array[mid] >= array[p1])
                p1 = mid;
            if(array[mid] <= array[p2])
                p2 = mid;
            // 特例2
            if(array[p1] == array[p2] && array[p1] == array[mid])
               return findByOrder(array, p1, p2);
        }
        return array[mid];
    }
    public int findByOrder(int[] array, int p1, int p2){
        int min = array[p1];
        for(int i=p1; i<=p2; i++){
            if(min > array[i])
                min = array[i];
        }
        return min;
    }
}

猜你喜欢

转载自blog.csdn.net/littlehaes/article/details/91384665