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

本文探讨如何在存在重复元素的数组中,通过循环遍历和二分法找出经过旋转后的最小值。方法一介绍了基础的循环遍历思路,方法二则展示了利用二分法的高效解决方案。适合理解数组操作和排序算法的优化实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

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

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

注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 
旋转一次的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]]

示例

输入:numbers = [3,4,5,1,2]
输出:1

输入:numbers = [2,2,2,0,1]
输出:0

方法一:循环遍历

思想:因为原来的数组是升序排列,那么旋转过后,最右边元素会出现两种情况
(1)较大值,且最小值在其左边的数组中
(2)最小值,此时他它左边的元素都大于等于该元素,直接输出即可
class Solution {
    public int minArray(int[] numbers) {
        int iLength = numbers.length;
        for(int i  = iLength-1; i > 0; i--)
        {
            if(numbers[i] < numbers[i-1])
            {
                    return numbers[i];
            }
        }
        return numbers[0];
    }
}

方法二:二分法

思想:
例如[4,5,6,7,1,2,3]
将一个数组按排序一分为二,分为左排序数组[4,5,6,7]和右排序数组[1,2,3]
其中左排序数组中任意元素>右排序数组中任意元素
按照二分法的思想,让nums[right]与nums[mid]进行比较,
将会出现三种情况
(1)nums[right]>nums[mid]
	可知mid处于右排序数组中,因此最小值在mid左边或者就是mid,此时使right = mid
(2)nums[right]<nums[mid]
	可知mid处于左排序数组中,因此最小值在mid右边,此时使left = mid + 13)nums[right]=nums[mid]
	此时mid状态位置,有可能在左排序数组,也有可能在右排序数组
	示例一 [1,0,1,1,1],mid在右排序数组中。
	示例二 [1,1,1,0,1],mid在左排序数组中
	解决方法,为避免过程复杂,出现这种情况直接顺序遍历


class Solution {
    public int minArray(int[] numbers) {
        int iLeft,iRight,iMid;
        iLeft = 0;
        iRight = numbers.length - 1;
        while(iLeft!=iRight)
        {
            iMid = (iLeft + iRight)/2;
            if(numbers[iMid] == numbers[iRight])
            {
                return findMin(iRight,iLeft,numbers);
            }
            else if(numbers[iMid] > numbers[iRight])
            {
                iLeft = iMid + 1;
            }
            else
            {
                iRight = iMid;
            }
        }
        return numbers[iRight];
    }

    public int findMin(int iRight,int iLeft,int[] nums)
    {
        int iMin= nums[iRight];
        for(int i = iLeft ; i <= iRight;i++)
        {
            if(iMin > nums[i])
            {
                iMin = nums[i];
            }
        }
        return iMin;
    }
}
讨论:为什么不用left和mid元素做对比?
解答:因为原数组是升序的,因此用left与mid做对比不能确定mid是在左排序数组还是右排序数组
示例一 [5,1,2,3,4],mid在右排序数组中。
示例二 [2,3,4,5,1],mid在左排序数组中

如果大家还有好的方法可以在评论区一起讨论一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值