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

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

示例1

输入

[3,4,5,1,2]

返回值

1

此题的的意思是 :

初始一个序列将任意数目的元素进行旋转到末尾,相当于两个递增的数组

例如:初始数组 1 2 3 4 5 旋转3个元素 为 4 5 1 2 3 然后找出最小的元素 1

思路:可以采用 暴力法 但是没有用到题目中递减排序的条件。

所以此处采用二分法的思想

找到中间值,和最左下标元素 i 或者最右下标元素 j 进行比较,然后逐渐缩小范围

此处缩减范围会出现以下情况(以下都是和最右下标进行比较)

  1. 中间值大 arr[mid] > arr[j] : 3 4 5 1 2 arr[mid] = 4 arr[j] = 2 所以此时最小元素肯定在 [mid+1 - j] 区间处,所以令 i = mid+1
  2. 中间值小 arr[mid] < arr[j] :5 1 2 3 4 同理 最小元素肯定在 [i - mid] 处 j = mid
  3. 相等 arr[mid] = arr[j] :1 1 1 0 1 根据题目不会出现此种情况,但是需要分析 此时不确定最小值在左边还是右边,则让 j–,慢慢缩小区间

代码

以右边为比较

 public int minNumberInRotateArray(int [] array) {
    
    
       if (array.length == 0) return 0; 
       int i = 0;
       int j = array.length-1;
       while (i < j){
    
    
           if (array[i] < array[j]) return array[i]; //当array[i] < array[j]则找到最小值
           int mid = (i + j) >>1;
           if (array[mid] > array[j]){
    
    
               i = mid+1;
           }else if (array[mid] < array[j]){
    
    
               j = mid;
           }else {
    
    
               j--;
           }
       }
        return array[i];
}

以左边为比较

public int minNumberInRotateArray(int[] array) {
    
    
        if (array.length == 0) return 0; 
        int i = 0, j = array.length - 1;
        while (i < j) {
    
    
            if (array[i] < array[j]) {
    
    
                return array[i];
            }
            int mid = (i + j) >> 1;
            if (array[mid] > array[i]) {
    
    
                i = mid + 1;
            } else if (array[mid] < array[j]) {
    
    
                j = mid;
            } else{
    
    
            i++;
            }
        }
        return array[i];
    }

时间复杂度分析:
普通情况 O(log2 n)
特殊情况O(n)

猜你喜欢

转载自blog.csdn.net/weixin_46078315/article/details/112329282