携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情
前言
- leetcode hot100,是大厂面试高频题,也是必刷算法题。精选了100道LeetCode上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,按照官方说的,熟练掌握这 100 道题,就具备了代码世界通行的基本能力。
leetcode581题(最短无序连续子数组)
本文来讲hot100第581题,最短无序连续子数组,本题题目比较容易理解,建议画张图,方便我们找到边界值。
给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
请你找出符合题意的 最短 子数组,并输出它的长度。
示例:
输入: nums = [2,6,4,8,10,9,15]
输出: 5
解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
输入: nums = [1,2,3,4]
输出: 0
输入: nums = [1]
输出: 0
进阶: 你可以设计一个时间复杂度为 O(n) 的解决方案吗?
分析
- 找到连续子数组,是一个区间,中间不能断,数组的长度最少为2
- 这段整数组进行升序排序,则整个数组都升序排序,所以我们可以知道除了子数组以外的数字,也是升序排列。
思路
由分析可知,我们需要找到边界,所以我们使用双指针法
- 我们先从左右两边分别遍历,知道不满足升序数组的边界
- 在两个边界内找到其中的最大值 max,以及最小值 min,
- 需要把左指针往左找到比 min 小的第一个数
- 需要把右指针往右找到比 max 大的第一个数
- 此时左指针和右指针中间的数,就是我们要找的排序的数
代码
var findUnsortedSubarray = function(nums) {
// 1. 双指针找边界
// 2. 找边界内的最大最小数
// 3. index相减
let len = nums.length, start = 0, end = len - 1
while (start < len - 1 && nums[start] <= nums[start + 1]) {
start ++
}
while (end > 0 && nums[end - 1] <= nums[end]) {
end --
}
// 设置最小值与最大值
let min = Infinity, max = -Infinity
// 注意这里是左闭右闭
for (let i = start; i <= end; i ++) {
min = Math.min(nums[i], min)
max = Math.max(nums[i], max)
}
// 因为我们第一次双指针找到不满足条件就不找了,所以边界是有可能不对的
// 如果与min小于最左边的值或者max大于最右边的值,说明我们找到边界不对,需要更新边界
while (nums[start] > min) {
start --
}
while (nums[end] < max) {
end ++
}
return end > start ? end - start - 1: 0
};
结语
- 此题也可以使用暴力法,既然题目是种类类型难度,那么我们肯定要用进阶的时间复杂度解决问题,此题的时间复杂度为
O(n)。