一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第28天,点击查看活动详情。
本题难度:⭐ ⭐ ⭐ ⭐
本题类型:算法、手写
跟着阿林一起刷算法题,阿林选的题全是面试高频题,今天介绍数组类型题目常用的套路——滑动窗口,同时也介绍一种求最小值或者最大值的小技巧。
知识点
- 算法思想之滑动窗口
- 求最小值或最大值的小技巧
题目描述
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
原题地址:209. 长度最小的子数组
题目要求:
输入: target = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的子数组。
输入: target = 4, nums = [1,4,4]
输出: 1
输入: target = 11, nums = [1,1,1,1,1,1,1,1]
输出: 0
解题思路 & 编码实现
解这道题我们首先会想到暴力法,循环两次,每次做对比,记录最小值。
这里有个小技巧,求最小值时,可以先设置初始值为 Infinity,之后如果有更小的,这个 Infinity 一定会被替换,这样写不用考虑一些边界问题,简单粗暴。
代码实现如下:
function minSubArrayLen (target, nums) {
let len = nums.length
let res = Infinity
for (let i = 0; i < len; i++) {
let sum = 0
for (let j = i; j < len; j++) {
sum += nums[j]
if (sum >= target) {
res = Math.min(res, j - i + 1);
break
}
}
}
return res == Infinity ? 0 : res;
}
当然,用暴力法解决了问题之后,接下来该考虑的就是如何去优化了,毕竟无脑遍历去解题在面试官那里可不会通过的。
这道题我们还是可以用快慢指针来做,思路是:
- 定义慢指针
i,快指针j - 定义
sum记录当前累加值,定义res记录要返回的长度。 - 慢指针先不动,快指针一直往后走,同时把累加值记录到
sum上。 - 当累加值
sum >= target时,把当前快慢指针索引之差记录到res上,再动慢指针,具体逻辑见下面的图解。
老规矩,先自己用文字“画图”,理清思路,不要光靠脑袋想。
慢指针 i,快指针 j
target = 7
初始状态:
sum = 2 res = Infinity
i
[2,3,1,4,3]
j
下一步:
sum = 5 res = Infinity
i
[2,3,1,4,3]
j
下一步:
sum = 6 res = Infinity
i
[2,3,1,4,3]
j
下一步:
sum = 10 res = 4
i
[2,3,1,4,3]
j
下一步:
sum = 8 res = 3
i
[2,3,1,4,3]
j
下一步:
sum = 5 res = 3
i
[2,3,1,4,3]
j
下一步:
sum = 8 res = 3
i
[2,3,1,4,3]
j
下一步:
sum = 7 res = 2
i
[2,3,1,4,3]
j
下一步:
sum = 3 res = 2
i
[2,3,1,4,3]
j
下一步:
快指针走完,循环结束
i
[2,3,1,4,3]
j
编码实现:
写代码时用更语意化的 fast 和 slow 来编码。
function minSubArrayLen (target, nums) {
let slow = 0, fast = 0
let len = nums.length
let res = Infinity
let sum = 0
while(fast < len) {
sum += nums[fast]
while (sum >= target) {
res = Math.min(fast - slow + 1, res)
sum -= nums[slow]
slow++
}
fast++
}
return res === Infinity ? 0 : res
}
看到这里,其实你已经不知不觉地理解了滑动窗口的思想。
在本题里,其实快慢指针之间的这个小区间,就可以理解成一个滑动的窗口。
随着快慢指针的移动,这个窗口在不停地扩大或者收缩,所以把它叫做滑动窗口。
滑动窗口是一种算法思想,或是一种解题方式,在数组上通过双指针同向移动(快慢指针)而解决的一类问题。
使用滑动窗口解决的问题通常是暴力解法的优化,掌握这一类问题最好的办法就是多练习,比如一道题用暴力法解决了,就去思考一下可不可以通过滑动窗口去优化一下,减少一些遍历的次数。
运行结果
vscode leetcode 插件 yyds! 上班“认真工作”的神器 🐶
结尾
阿林水平有限,文中如果有错误或表达不当的地方,非常欢迎在评论区指出,感谢~
如果我的文章对你有帮助,你的👍就是对我的最大支持^_^
我是阿林,输出洞见技术,再会!
上一篇:
下一篇“