壹 ❀ 引

早在10个月前,也就是去年,我记录了JS leetcode 寻找旋转排序数组中的最小值 题解分析,你不得不了解的二分法一题,那么这篇文章记录它的升级版,来自LeetCode154. 寻找旋转排序数组中的最小值 II,但是我现在回头看之前这篇文章,解题思路更像是找规律,有点难以记忆。我在前几天记录的另外两篇旋转数组中使用了相同的解题思路,所以为了思路上的统一,我想用相同的思路先把153. 寻找旋转排序数组中的最小值先重新梳理一遍,再来看它的升级版。回归正题,154. 寻找旋转排序数组中的最小值 II题目描述如下:

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 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 原来是一个升序排序的数组,并进行了 1 至 n 次旋转

进阶:

这道题是 寻找旋转排序数组中的最小值 的延伸题目。

允许重复会影响算法的时间复杂度吗?会如何影响,为什么?

贰 ❀ 思路分析与二分法

OK,我们还是先重新复习下153. 寻找旋转排序数组中的最小值这题,此题与升级版的题目唯一区别是数组中不存在重复项,即是一个数字不重复的被旋转的升序数组,让你找到数组中的最小值。

因为前面我们已经做了两题关于旋转数组的题目,已经总结出了一种二分法的思路,这里直接再次套用这种解题思路,比如要找到[4,5,0,1,2,3]中的最小值,我们依然可以用mid与nums[0]进行比较,如果mid>=nums[0]说明升序部分在左侧,如果mid<nums[0]说明升序部分在右侧,我们用图画出来,感受下这个规律:

图1

如上图,通过中间数mid与nums[0]的大小比较就能知道升序在哪一边。如果升序在这一边,那么最小值一定在不是升序的这一边,看图自己感受下。当然有个特例,数组没旋转的情况下,也满足mid>=nums[0],但最小值其实在左侧,没关系,因为只有未旋转的数组nums[0]<=nums[length-1],比如:

let arr = [1];
arr[0]<=arr[arr.length-1]; //true
let arr = [1,2]
arr[0]<=arr[arr.length-1]; //true

让我们来实现这段代码:

var findMin = function (nums) {
let n = nums.length;
let l = 0;
let r = n - 1;
// 数组未旋转或者数组只有一位的情况
if (nums[l] <= nums[r]) {
return [nums[l]];
};
// 能走到这,说明数组一定旋转了
while (l < r) {
let mid = Math.floor((l + r) / 2);
// 如果mid>=nums[0],升序在左侧,最小在右侧,修改l的指针
if (nums[mid] >= nums[0]) {
// 为什么要加1,请看图感受
l = mid+1;
} else {
//反之升序在右侧,最小值在左侧,修改r指针
r = mid;
}
}
return nums[l] <= nums[r] ? nums[l] : nums[r];
};

我们来解释下这段代码中的几个注意点,第一个问题,为什么是nums[mid] >= nums[0],因为我们取mid是向下取整,比如数组[2,1],mid取的其实是nums[0]也就是2,因为nums[mid]其实等于nums[0],其实就是为了兼容这种情况。

第二个问题,为什么l=mid+1,而r不是mid-1呢?其实看我们上面列举的旋转的数组图示,你会发现当mid>=nums[0]时,由于升序在左侧,最小值在右侧,而且最小一定不可能是mid,所以直接mid+1,不然假设数组是[2,1]的情况,你会发现由于l=mid会一直等于0,然后陷入死循环。

l不是mid-1看图其实也很清楚,因为有可能mid就是最小值,所以我们不能舍弃掉,这也算是画图找规律的一种,但整体思路其实还是与之前两道题相同。

OK,那么到这里我们用之前mid与nums[0]比较的思路,重新把这道题解了下,算是把思路给统一了,不然一道题一个思路也确实难以记忆。

那么回到它的升级版,也就是存在重复数的情况,我们甚至可以暴力点,直接数组去重后套用上面的代码,比如:

/**
* @param {number[]} nums
* @return {number}
*/
var findMin = function (nums) {
// 去重
nums = [...new Set(nums)]
// 下面不变
let n = nums.length;
let l = 0;
let r = n - 1;
// 数组未旋转或者数组只有一位的情况
if (nums[l] <= nums[r]) {
return [nums[l]];
};
// 能走到这,说明数组一定旋转了
while (l < r) {
let mid = Math.floor((l + r) / 2);
// 如果mid>=nums[0],升序在左侧,最小在右侧,修改l的指针
if (nums[mid] >= nums[0]) {
// 为什么要加1,请看图感受
l = mid+1;
} else {
//反之升序在右侧,最小值在左侧,修改r指针
r = mid;
}
}
return nums[l] <= nums[r] ? nums[l] : nums[r];
};

当然既然题目都给了重复数字,咱们直接去重多少差点意思,如果不去重我们如何解决这道题呢?

举个例子,假设数组为[3,1,3],上面的代码会直接挂掉,因为一开始就满足了nums[l] <= nums[r],其实在JS Leetcode 81. 搜索旋转排序数组 II 题解,补救二分法的可行性中,我们就解释了重复元素导致二分法特性丢失的问题,而挽救这种特性的办法就是,当数组的nums[l]===nums[r]时,我让任意一方的指针进行缩进,比如r++即可,因为给无数个3和给一个3,并不会影响到最终的结果判断。

所以我们修改下上方的代码,不用去重就是这样:

var findMin = function (nums) {
let n = nums.length;
let l = 0;
let r = n - 1;
while (l < r) {
// 只要左右指针相同,就让r--,比如[3,1,3]就会变成[3,1]
if (nums[l] <= nums[r]) {
return [nums[l]];
};
// 这个移进来了,如果放外面可能有[3,1,3]这种,同时也用于解决1个元素的情况以及未旋转的情况
if (nums[l] === nums[r]) {
r--;
break;
};
let mid = Math.floor((l + r) / 2);
// 如果mid>=nums[0],升序在左侧,最小在右侧,修改l的指针
if (nums[mid] >= nums[0]) {
// 为什么要加1,请看图感受
l = mid + 1;
} else {
//反之升序在右侧,最小值在左侧,修改r指针
r = mid;
}
}
return nums[l] <= nums[r] ? nums[l] : nums[r];
};

那么本文就到这里了,相关系列题型可见下方。

JS leetcode 153. 寻找旋转排序数组中的最小值 题解分析,你不得不了解的二分法

JS Leetcode 33. 搜索旋转排序数组题解,图解旋转数组中的二分法

JS Leetcode 81. 搜索旋转排序数组 II 题解,补救二分法的可行性

JS Leetcode 154. 寻找旋转排序数组中的最小值 II 题解分析的更多相关文章

  1. Java实现 LeetCode 154 寻找旋转排序数组中的最小值 II(二)

    154. 寻找旋转排序数组中的最小值 II 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 请找 ...

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

    题目链接 : https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/ 题目描述: 假设按照升序排序的数组在预 ...

  3. Leetcode之二分法专题-154. 寻找旋转排序数组中的最小值 II(Find Minimum in Rotated Sorted Array II)

    Leetcode之二分法专题-154. 寻找旋转排序数组中的最小值 II(Find Minimum in Rotated Sorted Array II) 假设按照升序排序的数组在预先未知的某个点上进 ...

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

    title: 寻找旋转排序数组中的最小值II 题目描述 题目链接:寻找旋转排序数组中的最小值II 解题思路 和上题同理:数组特点有 nums[mid] < nums[right],最小值肯定在m ...

  5. 领扣(LeetCode)寻找旋转排序数组中的最小值 个人题解

    假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 请找出其中最小的元素. 你可以假设数组中不存在重 ...

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

    转跳点:--\(˙<>˙)/-- 原本打算大年三十十一起写完的,结果这篇拖到了年初一…… 这道题比刚刚那道,麻烦一点,因为有重复,所以我们需要考虑重复的情况,就是刚刚的两种情况变成了三种: ...

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

    154.寻找旋转排序数组中的最小值 II 描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). ...

  8. LeetCode:寻找旋转排序数组中的最小值【153】

    LeetCode:寻找旋转排序数组中的最小值[153] 题目描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0 ...

  9. lintcode:寻找旋转排序数组中的最小值 II

    寻找旋转排序数组中的最小值 II 假设一个旋转排序的数组其起始位置是未知的(比如0 1 2 4 5 6 7 可能变成是4 5 6 7 0 1 2). 你需要找到其中最小的元素. 数组中可能存在重复的元 ...

  10. Java实现 LeetCode 153 寻找旋转排序数组中的最小值

    153. 寻找旋转排序数组中的最小值 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 请找出其中 ...

随机推荐

  1. for-each循环使用iterator进行遍历

    示例如下: public static void main(String args[]) { List list = new LinkedList(); list.add("aa" ...

  2. 从零开始制作PyTorch的Singularity容器镜像

    技术背景 在前面的博客中,我们大篇幅的使用到了Docker和Singularity这两种常见的容器化编程环境解决方案,使得我们的各个编程环境能够更好的隔离.如果要展开讲解容器化编程环境的重要性的话,我 ...

  3. Linux-用户管理-useradd-userdel-id

  4. 【水一篇】骚操作之net 6的winform启动的同时启动Net 6 WebApi【同一套代码】

    引言 有段时间没有写博客了,不知道写什么,加上最近一直在玩单片机方面的东西,所以有一些懈怠.首先呢,为什么会有这么一个问题,是在一个QQ群里,有看到有人提问,能不能在启动Winform的同时去启动一个 ...

  5. [转帖]金仓数据库KingbaseES误删除系统超级用户(superuser)权限的恢复方式

    https://blog.csdn.net/arthemis_14/article/details/129879269 在使用KingbaseES数据库的时候,系统默认存在一个跟系统初始化用户同名的S ...

  6. 申威下单盘SSD与四块盘RAID5的性能测试结果

    申威下单盘SSD与四块盘RAID5的性能测试结果 背景 背景不在说了 申威服务器.. 结论 天坑 做了raid写入性能下降明显. 充分怀疑驱动不行. 四快盘的raid5 跟单盘的读几乎没区别. 感觉这 ...

  7. [转帖]Linux禁用CPU省电状态/Linux系统性能调优

    https://www.jianshu.com/p/945168b47487 How to Disable CPU Power Saving States on a Redhat or Suse Li ...

  8. [转帖]官网:Nacos的授权验证

    https://nacos.io/zh-cn/docs/v2/guide/user/auth.html 注意 Nacos是一个内部微服务组件,需要在可信的内部网络中运行,不可暴露在公网环境,防止带来安 ...

  9. BMC修改密码

    公司里的服务器都托管出去了, 为了好维护, 都给自己的机器设置了BMC远程管理的端口, 安全起见自己修改了密码. 方法很简单.默认用户密码是 用户:root 密码: root 用户:admin 密码: ...

  10. 使用shell进行简单分析增量更新时间的方法

    使用shell进行简单分析增量更新时间的方法 思路 产品里面更新增量时耗时较久, 想着能够简单分析下哪些补丁更新时间久 哪些相同前缀的补丁更新的时间累积较久. 本来想通过全shell的方式进行处理 但 ...