数据结构习题--寻找旋转排序数组中的最小值

数据结构习题--寻找旋转排序数组中的最小值

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = 0,1,2,4,5,6,7 在变化后可能得到:

若旋转 4 次,则可以得到 4,5,6,7,0,1,2

若旋转 7 次,则可以得到 0,1,2,4,5,6,7

可以理解旋转几次,每一次就是把最后一个数拿到数组最前面

注意,数组 a\[0, a1, a2, ..., an-1] 旋转一次 的结果为数组 a\[n-1, a0, a1, a2, ..., an-2] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

方法一:复杂度O(n)

分析

我们知道原来的数组是单调递增的,而经历过旋转之后,它具有的特点是前面一段和后面一段都是单调递增的,但是前面一段的最小值大于后面一段的最大值,而我们需要寻找的最小值,是在两段的分界点

而对于我们取第一个元素为最小值,遍历数组,当有元素比其小,就退出循环,该值就是我们需要寻找的最小值

代码

java 复制代码
public int findMin(int[] nums) {
        int min = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] < min){
                return nums[i];
            }
        }
        return min;
    }

方法二:二分查找 复杂度O(logn)

分析

我们知道原来的数组是单调递增的,而经历过旋转之后,它具有的特点是前面一段和后面一段都是单调递增的,但是前面一段的最小值大于后面一段的最大值,而我们需要寻找的最小值,是在两段的分界点

而我们设置一个low在数组最左边,设置high在数组最右边,而mid为其中间,当mid的元素小于high的元素时,我们就不需要管其右边的元素,直接令high到mid的位置,然后重新计算mid,当mid的元素不大于high的元素时,我们令low = mid + 1,

代码

java 复制代码
    public int findMin(int[] nums) {
        /**
         * high 表示右边的元素
         * low 表示左边的元素
         */
        int high = nums.length- 1;
        int low = 0;
        while (low < high){
            // 寻找中间的数,进行二分
            int mid = (high + low) / 2;
            // 当中间的数小于右边的数,更新此位置为右边
            if (nums[mid] < nums[high]){
                //如果中间值小于最大值,则最大值减小
//            疑问:为什么 high = mid;而不是 high = mid-1;
//            解答:{4,5,1,2,3},如果high=mid-1,则丢失了最小值1
                high = mid;
            }else {
                // 如果中间值大于最大值,最小值变大
                // 疑问:为什么 low = mid+1;而不是 low = mid;
//                 解答:{4,5,6,1,2,3},nums[mid]=6,low=mid+1,刚好nums[low]=1
//                 继续疑问:上边的解释太牵强了,难道没有可能low=mid+1,正好错过了最小值
//                 继续解答:不会错过!!! 如果nums[mid]是最小值的话,则其一定小于nums[high],走if,就不会走else了
                low = mid + 1;
            }
        }
        // 疑问:为什么while的条件是low<high,而不是low<=high呢
//         解答:low<high,假如最后循环到{*,10,1,*}的这种情况时,nums[low]=10,nums[high]=1,nums[mid]=10,low=mid+1,
//             直接可以跳出循环了,所以low<high,此时low指向的就是最小值的下标;
//             如果low<=high的话,low=high,还会再不必要的循环一次,此时最后一次循环的时候会发生low==high==mid,
//             则nums[mid]==nums[high],则会走一次else语句,则low=mid+1,此时low指向的是最小值的下一个下标,
//             则需要return[low-1]
        return nums[low];
    }
相关推荐
小郎君6587 分钟前
Vue 多标签页的加载态设计:为什么我没有用 Suspense 实现 PageLoading
vue.js·算法
JJJennie77737 分钟前
MAI Gateway私有化部署全攻略:大模型网关如何接入?附架构图
算法·gateway·ai网关·魔芋ai
東隅已逝,桑榆非晚44 分钟前
算法3.双指针法-快乐数
c++·笔记·学习·算法
专注仿真1 小时前
卷积神经网络(CNN)算法详解
人工智能·python·算法·代码·大模型训练
FII工业富联科技服务1 小时前
多智能体如何进入制造现场?从业务协同到数字孪生验证
大数据·人工智能·算法·机器人·制造·数字孪生
≮傷£≯√1 小时前
httpserver_QNetWorkClient
算法
Evand J1 小时前
【PMSM例程11】永磁同步电机(PMSM)基于UKF的转速与转子位置估计。附下载链接
算法·matlab·卡尔曼滤波·永磁同步电机·ukf·pmsm·位置估计
货拉拉技术1 小时前
记忆即智能:重构对话式AI Agent认知基座的四层渐进式记忆与自进化系统
人工智能·算法
杜 硕1 小时前
从零开始的C++生活——第六讲——02
c++·算法·生活
小超人诞生日记2 小时前
C++ STL 反向迭代器:从源码框架到适配器实现
c++·算法