Java——旋转数组的最小数字

题目链接

牛客在线oj题——旋转数组的最小数字

题目描述

有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。

数据范围:1≤n≤10000,数组中任意元素的值:0≤val≤10000
要求:空间复杂度:O(1) ,时间复杂度:O(logn)

题目示例

示例1

输入:
[3,4,5,1,2]

返回值:
1

示例2

输入:
[3,100,200,3]

返回值:
3

解题思路

根据题目中给出的旋转定义,数组被切割成两个非递减的序列,而序列的连接处就是最小值的地方。因此可以得出当arr[i] > arr[i + 1]的时候,arr[i + 1]就是那个最小值

还有一种更加高效的方法:使用二分查找进行定位
根据旋转的定义可以不仅可以得出数组前半部分和后半部分都是非递减的序列,并且数组的前半部分一定比后半部分大
在这里插入图片描述
我们按照二分查找的思想,分别定义left , right , mid

如果left小于等于mid,说明left和mid位于同一个非递减序列,而right位于另一个非递减序列,因此最小值一定在right所在的非递减序列,因此这时应该让left = mid
在这里插入图片描述
而如果left大于mid,说明right和mid位于同一个非递减序列,而left位于另一个非递减序列,因此最小值一定在left所在的非递减序列或mid所在位置,因此这时应该让right = mid
在这里插入图片描述
还需要注意一点,题目中说的是非递减序列,因此可能出现多个相等的数字,这时如果left和right和mid都相等,说明最小值就在left和right这个序列之间,只能通过遍历进行搜索
在这里插入图片描述

完整代码

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        int left = 0;
        int right = array.length - 1;
        int mid = 0;
        while(array[left] >= array[right]){
            if(right - left == 1){
                mid = right;
                break;
            }
            mid = left + ((right - left) >> 1);
            if(array[left] == array[right] && array[left] == array[mid]){
                int result = array[left];
                for(int i = left + 1; i < right; i++){
                    if(array[i] < result){
                        result = array[i];
                    }
                }
                return result;
            }
            if(array[mid] >= array[left]){
                //结果应该在右半部分
                left = mid;
            } else {
                right = mid;
            }
        }
        return array[mid];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值