(每日一题)旋转数组的最小数字(二分查找)

目录

一、题目描述

二、题解


一、题目描述

描述:
        有一个长度为 n 的非降序数组,比如[1,2,3.4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
数据范围: 1 <= n <= 10000,数组中任意元素的值: 0 <= val <= 10000要求: 空间复杂度: 0(1),时间复杂度: (logn)

示例:

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

返回值:1

二、题解

1.分析

 核心思想:通过不断缩小搜索范围,利用二分查找的方式快速找到旋转排序数组中的最小值。它的时间复杂度为O(logN),其中N是数组的长度。

具体步骤如下:

(1)定义两个指针, leftright ,分别指向数组的最左端和最右端。
(2)进入循环,判断条件是 left 小于 right ,即搜索范围还没有缩小到只剩一个元素。
(3)在循环中,计算中间位置 mid ,通过将 leftright 相加再除以2得到。
(4)判断中间位置的值 nums[mid] 和右边界的值 nums[right] 的大小关系。
(5)如果 nums[mid] 大于 nums[right] ,说明最小值在中间位置的右侧,将 left 移动到 mid 的右侧一位。
(6)如果 nums[mid] 小于 nums[right] ,说明最小值在中间位置的左侧或者就是中间位置本身,将 right 移动到 mid 的位置。 
(7)如果 nums[mid] 等于 nums[right] ,无法确定最小值在哪一侧,但可以确定的是,由于存在重复元素,可以将右边界向左移动一位。
(8)循环结束后,返回 nums[left] 作为最小值。

2.代码

代码如下:

public static int fincMinNumber(int[] nums){
    int left = 0; // 左边界
    int right = nums.length-1; // 右边界
    while (left<right){
        int mid = (left+right)/2; // 中间位置
        if (nums[mid]>nums[right]) // 如果中间位置的值大于右边界的值
            left=mid+1; // 将左边界移动到中间位置的右侧
        else if(nums[mid]<nums[right]) // 如果中间位置的值小于右边界的值
            right=mid; // 将右边界移动到中间位置
        else
            right--; // 如果中间位置的值等于右边界的值,则将右边界向左移动一位
    }
    return nums[left]; // 返回最小值
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ai旅人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值