leetcode 154. 寻找旋转排序数组中的最小值 II |刷题打卡

204 阅读2分钟

本文正在参与掘金团队号上线活动,点击 查看大厂春招职位

一、题目描述:

154. 寻找旋转排序数组中的最小值 II

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

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

示例 1:

输入:nums = [1,3,5]
输出:1

示例 2:

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

提示:

  • n == nums.length
  • 1 <= n <= 5000
  • -5000 <= nums[i] <= 5000
  • nums 原来是一个升序排序的数组,并进行了 1n 次旋转

进阶:

  • 这道题是 寻找旋转排序数组中的最小值 的延伸题目。
  • 允许重复会影响算法的时间复杂度吗?会如何影响,为什么?

二、思路分析:

  1. 遍历后查找最小值 AC代码
/**
 * @param {number[]} nums
 * @return {number}
 */
var findMin = function(nums) {
    let min = nums[0];
    for(let i = 1; i < nums.length; i ++) {
        if(nums[i] < min) min = nums[i];
    }
    return min;
};

执行结果

执行结果:通过
执行用时:96 ms, 在所有 JavaScript 提交中击败了21.48%的用户
内存消耗:39.1 MB, 在所有 JavaScript 提交中击败了22.46%的用户

缺点:时间复杂度最大

  1. 数组重新升序排序后取第一个 AC代码
/**
 * @param {number[]} nums
 * @return {number}
 */
var findMin = function(nums) {
    nums.sort((a, b) => {
        return a - b;
    });
    return nums[0];
};

执行结果

执行结果:通过
执行用时:88 ms, 在所有 JavaScript 提交中击败了55.08%的用户
内存消耗:38.9 MB, 在所有 JavaScript 提交中击败了66.60%的用户

缺点:时间复杂度也最长

  1. 二分法
  • 查找有序数组,尝试使用二分法
  • 使用(end - start) / 2获得中间位置mid,使用Math.floor向下取整
  • 判断中间位置值nums[mid]和末尾位置值nums[end]是否是升序,是升序则说明最小值在中间位置的左边部分,把结束位置置为原中间位置end = mid
  • 若是不是升序,因为存在重复元素,所以再判断中间位置值是否大于末尾位置值,若大于则最小值在右边部分,把开始位置置为原中间位置加一start = mid + 1
  • 否则末尾位置值向左移一位
  • 继续二分,直到起始位置不小于结束位置,返回起始位置的值nums[start] AC代码
/**
 * @param {number[]} nums
 * @return {number}
 */
var findMin = function(nums) {
    let start = 0;
    let end = nums.length - 1;
    let min = nums[0];
    while(start < end) {
        let mid = start + Math.floor((end - start) / 2);
        if(nums[mid] < nums[end]) {
            end = mid;
        } else if(nums[mid] > nums[end]) {
            start = mid + 1;
        } else {
            end --;
        }
    }
    return nums[start];
};

执行结果

执行结果:通过 显示详情
执行用时:84 ms, 在所有 JavaScript 提交中击败了73.83%的用户
内存消耗:39 MB, 在所有 JavaScript 提交中击败了57.42%的用户

三、总结:

  • 数组遍历查找效率最低
  • 利用数组自带排序sort可利用JavaScript内部优化,提升部分效率
  • 二分查找提高查找效率