LeetCode题解—旋转数组的最小数字

简介: 今天继续算法题:旋转数组的最小数字

前言


今天继续算法题:旋转数组的最小数字


题目:旋转数组的最小数字


把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [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,2,3,4,5]
//旋转之后
[3,4,5,1,2]


找到其中的最小数字。


那么我们很容易想到的第一中解法就是遍历数组,然后找到某一个数字比它前面一个数字小的时候,那么这个数字就是我们要找的最小数字。


因为正常来说都是后面数字大于前数字,所以出现小于前数字,那么就是这个旋转数组的分界点,也就是最小数字了。


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


方法消耗情况


以后不写这个了。由于每次测试用例不同,造成的结果也相差太大,没有参考性。


时间复杂度


遍历一次数组,所以时间复杂度为O(n)


空间复杂度


没有用到另外的空间,所以空间复杂度为O(1)


解法二


二分法。


有的人可能会疑惑,二分法不是用来查找顺序数组的吗,这个旋转之后也算吗?


我们回顾下二分法的关键点就是:


取任意一个关键数字,都能通过判断 来确定在我们要的值在哪个区间(关键数字的前后)。


那么在我们的旋转数组中,能做到这一点吗?


比如我们取中间值a和最后值b,如果a大于b,就说明这个分界值在这a和b之间,a之前的数据是正确排序的。


如果a小于b,说明分界值在a之前,a到b之间的数据是正确排序的。


比如刚才的[3,4,5,1,2],中间值5大于最后的值2,说明分界值在5和2之间,也就是1了。


class Solution {
    public int minArray(int[] numbers) {
        int left=0;
        int right=numbers.length-1;
        //二分法查找条件
        while(left<right){
            //找到中间点
            int mid=left+(right-left)/2;
            if(numbers[mid]<numbers[right]){
                right=mid;
            }else if(numbers[mid]>numbers[right]){
                left=mid+1;
            }else{
                right--;
            }
        }
        return numbers[left];
    }
}


其中right=mid,left=mid+1的原因是因为,当numbers[mid]<numbers[right]的时候,mid有可能为最小的那个数值对应的下标,所以right要设置成mid。


numbers[mid]>numbers[right]的情况下,mid不可能为最小,所以设置为mid+1


时间复杂度


二分法最坏情况:


n/(2的x次方)=1,x=long2n。所以时间复杂度为O(longn)

还有一种情况是所有元素全部相同,这种情况下每次都执行right-1,所以时间复杂度为O(n)


空间复杂度


没有用到另外的空间,所以空间复杂度为O(1)


参考


https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/submissions/

目录
相关文章
|
18天前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
36 0
|
2月前
|
算法
LeetCode第53题最大子数组和
LeetCode第53题"最大子数组和"的解题方法,利用动态规划思想,通过一次遍历数组,维护到当前元素为止的最大子数组和,有效避免了复杂度更高的暴力解法。
LeetCode第53题最大子数组和
|
2月前
|
存储 Java API
LeetCode------合并两个有序数组(4)【数组】
这篇文章介绍了LeetCode上的"合并两个有序数组"问题,并提供了三种解法:第一种是使用Java的Arrays.sort()方法直接对合并后的数组进行排序;第二种是使用辅助数组和双指针技术进行合并;第三种则是从后向前的双指针方法,避免了使用额外的辅助数组。
LeetCode------合并两个有序数组(4)【数组】
|
2月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
99 2
LeetCode------找到所有数组中消失的数字(6)【数组】
这篇文章介绍了LeetCode上的"找到所有数组中消失的数字"问题,提供了一种解法,通过两次遍历来找出所有未在数组中出现的数字:第一次遍历将数组中的每个数字对应位置的值增加数组长度,第二次遍历找出所有未被增加的数字,即缺失的数字。
|
2月前
|
前端开发
LeetCode------移动零(5)【数组】
这篇文章介绍了LeetCode上的"移动零"问题,提出了一种使用双指针的原地操作解法,该方法首先将非零元素移动到数组前端并保持相对顺序,然后填充后续位置为零,以达到题目要求。
|
2月前
【bug记录】旋转链表与力扣报错:member access within null pointer of type ‘struct ListNode‘
【bug记录】旋转链表与力扣报错:member access within null pointer of type ‘struct ListNode‘
|
13天前
【LeetCode-每日一题】 删除排序数组中的重复项
【LeetCode-每日一题】 删除排序数组中的重复项
16 4
|
13天前
|
机器学习/深度学习
Leetcode第48题(旋转图像)
这篇文章介绍了LeetCode第48题“旋转图像”的解题方法,通过原地修改二维矩阵实现图像的顺时针旋转90度。
23 0
Leetcode第48题(旋转图像)
|
13天前
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
12 0
Leetcode第三十三题(搜索旋转排序数组)