JAVA练习21-旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。

示例 1:
输入:[3,4,5,1,2]
输出:1

示例 2:
输入:[2,2,2,0,1]
输出:0

分析:

方法1:普通遍历优化

最简单的解法就是直接遍历记录每一次的最小值,不过考虑到数组是一个旋转数组,那么可以优化遍历条件,因为大部分数组的是一个两段升序的情况,而且第二段升序的第一个数字就是数组最小值,所以当遍历到有值比第一个值小时,直接返回该值,终止循环。

时间复杂度:O(n)
空间复杂度:O(1)

class Solution {
    public int minArray(int[] numbers) {
        int len = numbers.length;
        for(int i = 1; i < len; ++i){
            if(numbers[0] > numbers[i]){
                return numbers[i];
            }
        }
        return numbers[0];
    }
}

方法2:二分查找

由方法1知道大部分数组第二段升序的第一个数字就是数组最小值,拿 [3,4,5,1,2] 举例,最小值就是 1,那么我们是不是就可以从中间开始查找,定义两个指针 i j 分别指向开头和结尾,令 m = (i + j) / 2 为中间点,指针满足三个条件:

  1. numbers[ j ] < numbers[ m ] 时,最小值一定在中间点右边,即在区间 ( m , j ] 内,因此令 i = m + 1

  2. numbers[ j ] > numbers[ m ] 时,因为 m 是整除,所以最小值一定在中间点左边或中间点,即在区间 [ i , m ] 内,因此令 j = m

  3. numbers[ j ] = numbers[ m ] 时,不确定在那边,不过因为是两个一样的数,所以我们可以舍弃其中的一个,但必须保证最小值在新的区间内。因为当两个点值相等的时候,[ i , m ] 一定满足升序条件,所以我们只能令 j = j - 1

时间复杂度:O(log2 ​n)
空间复杂度:O(1) 

class Solution {
    public int minArray(int[] numbers) {
        int i = 0, j = numbers.length - 1;
        while(i < j){
            int m = (i + j) / 2;
            if(numbers[j] < numbers[m]){
                i = m + 1;
                continue;
            }
            if(numbers[j] > numbers[m]){
                j = m;
                continue;
            }
            j--;
        }
        return numbers[i];
    }
}

题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

什巳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值