手撕leetcode153题

这篇博客介绍了LeetCode第153题的解决方案。在旋转的升序数组中寻找最小元素,通过分析旋转数组的特性,提出了三种方法:数组重排序、逐个比较和二分查找。其中,二分查找方法具有最优的时间复杂度O(logn)。文章提供了每种方案的思路和代码实现。

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

题目

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

请找出其中最小的元素。

你可以假设数组中不存在重复元素。

示例 1:

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

输入: [4,5,6,7,0,1,2]
输出: 0

分析

需要注意的是这个数组最开始是有序的,如{1,2,3,4,5,6}。

数组旋转的是什么意思?就是数组中的元素向后移动,末尾的元素移到头就到数组头然后继续后移。

数组后移1位,即{6,1,2,3,4,5}
数组后移2位,即{5,6,1,2,3,4}
数组后移3位,即{4,5,6,1,2,3}

现在数组旋转的概念介绍清楚了,那么我在来看一下旋转后的数组的规律

  • 一个升序序列变成了两个升序序列
  • 最小值小于其左边的值
方案一:数组重排序

将数组重新按升序排序,然后取第一个元素即是最小值

代码实现
 	/**
     * 求升序数组旋转后的最小值  排序求解
     *
     * @param nums
     * @return
     */
    public int findMin(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            for (int j = i; j < nums.length - i; j++) {
                if (nums[i] > nums[j]) {
                    int temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                }
            }
        }

        return nums[0];
    }

时间复杂度O(n2),空间复杂度O(n)。

方案二:逐个比较

将数组第一个元素置为最小值,逐个比较,如果其值更小则替换,取所有小值的最小值即为结果

代码实现
 	/**
     *
     * @param nums
     * @return
     */
    public int findMinByDP(int[] nums) {
        int iMin = nums[0];
        int min = nums[0];
        for (int i = 0; i < nums.length; i++) {
            iMin = Math.min(iMin, nums[i]);
            min = Math.min(iMin, min);
        }
        return min;
    }

时间复杂度O(n),空间复杂度O(n)。

方案三:二分查找

如果arr[length - 1] > arr[0],说明数组没有旋转,最小值是arr[0]。
否则说明数组旋转了,
我们去数组的中间值arr[mid],
如果arr[mid]>arr[0]说明最小值在数组的右半部分。
最小值出现在左遍的值>右边的值,右边值即是最小值(数组升序)

代码实现
	/**
     * 二分查找
     * @param nums
     * @return
     */
    public int findMinByBinary(int[] nums) {

        if (nums.length == 1) {
            return nums[0];
        }

        if (nums[nums.length -1] > nums[0]){
            return nums[0];
        }

        int left = 0;
        int right = nums.length -1;
        int mid;

        while (left <= right) {
            mid = (left + right) / 2;

            if (nums[mid] > nums[mid + 1]) {
                return nums[mid + 1];
            }

            if (nums[mid] < nums[mid - 1]) {
                return nums[mid];
            }

            if (nums[mid] > nums[0]) {
                left = mid + 1;
            }else {
                right = mid - 1;
            }
        }
        return nums[left];
    }

时间复杂度O(logn),空间复杂度O(n)。

关注不迷路

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值