旋转数组的最小值

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。

思路及解答

import java.util.Scanner;
import java.io.*;
 
    public class Main {
 
        public static void main(String[] args) throws Exception{
            BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
            String[] strings = bf.readLine().split(" ");
            int[] arr = new int[strings.length];
            for (int i = 0; i < arr.length; i++) {
                arr[i] = Integer.parseInt(strings[i]);
            }
            
            int res = solution(arr);
            System.out.print(res);
            bf.close();
        }
 
        /*
        * 思路:
        * 1.我们注意到旋转之后的数组实际上可以划分为两个排序的子数组
        * 2.而且前边的子数组大于或者后边的子数组
        * 3.我们还注意到最小的元素刚好是这两个子数组的分界线
        * 4.因为数组的部分排序的,所有我们利用二分查找法来找到数组中的最小元素
        * 5.接着我们可以找到数组中间的元素
        * 6.如果数组中间的元素位于前面的递增子数组,那么它应该大于或等于第一个指针指向的元素,此时
        * 数组中的最小元素位于该中间元素的后边
        * 7.如果数组中间的元素位于后面的递增子数组,那么它应该小于或等于第二个指针指向的元素,此时
        * 数组中的最小元素位于该中间元素的前边
        * 8.第一个指针总是指向前面递增数组的元素,而第二个指针总是指向后面递增数组的元素
        * 9.最终,第一个指针指前面子数组的最后一个元素,而第二个指针指向后面子数组的第一个元素
        * 10.也就是说,它们最终会指向两个相邻的元素,而第二个指针指向的刚好是最小元素
        *
        * 11.如果排序数组前面0个,也就是说如果数组是完全有序的,那么直接返回第一个元素
        *
        * 12.出现了l和r指向的元素相同并且中间的元素也相同的情况【1 0 1 1 1】
        *
        * */
        public static int solution(int[] arr){
 
            if(arr == null || arr.length == 0) return 0;
 
            int l = 0;
            int r = arr.length - 1;
            int min = l;
 
            while(arr[l] >= arr[r]){
                int mid = (l + r) >> 1;
                if(r - l == 1){
                    min = r;
                    break;
                }
 
                //如果下标为 l、r 和 m 指向的数字相等,则只能顺序查找
                if(arr[l] == arr[r] && arr[mid] == arr[r]){
                   return minInOrder(arr, 0, arr.length-1);
                }
 
                if(arr[mid] >= arr[l]){
                    l = mid;
                }else if(arr[mid] <= arr[r]){
                    r = mid;
                }
            }
 
            return arr[min];
        }
 
        public static int minInOrder(int[] arr, int l, int r){
            int res = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if(arr[i] < res){
                    res = arr[i];
                }
            }
            return res;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值