文章目录
- 写在前面
- Tag
- 题目来源
- 题目解读
- 解题思路
- 方法一:暴力枚举
- 方法二:滑动窗口
- 写在最后
写在前面
本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更……
专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删:
- Tag:介绍本题牵涉到的知识点、数据结构;
- 题目来源:贴上题目的链接,方便大家查找题目并完成练习;
- 题目解读:复述题目(确保自己真的理解题目意思),并强调一些题目重点信息;
- 解题思路:介绍一些解题思路,每种解题思路包括思路讲解、实现代码以及复杂度分析;
- 知识回忆:针对今天介绍的题目中的重点内容、数据结构进行回顾总结。
Tag
【滑动窗口】【双指针】【暴力枚举】【数组】
题目来源
面试经典150 | 209. 长度最小的子数组
题目解读
给定一个长度为 n
的数组以及一个正整数 target
。找出数组中连续子数组和大于等于 target
的最小长度。
解题思路
方法一:暴力枚举
最容易想到的方法是枚举所有连续子数组的,如果某个连续子数组的元素和大于等于 target
,则更新最小的子数组长度。
实现代码
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int n = nums.size();
if (n == 0) {
return 0;
}
int ans = INT_MAX;
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += nums[j];
if (sum >= s) {
ans = min(ans, j - i + 1);
break;
}
}
}
return ans == INT_MAX ? 0 : ans;
}
};
复杂度分析
时间复杂度: O ( n 2 ) O(n^2) O(n2)。
空间复杂度: O ( 1 ) O(1) O(1)。
方法二:滑动窗口
我们使用一个滑动窗口在数组上进行滑动,初始滑动窗口的始末位置指针 l
和 r
都为 0
,暂时固定开始的位置不动,一直向右滑动滑动窗口的末位置 l
,并及时更新滑动窗口内的数组元素和 sum
:
- 如果
sum >= target
,说明当前的滑动窗口范围内的数组是一个合适的连续子数组,更新res = min(res, r - l + 1)
;res
初始为INT_MAX
; - 这个时候,我们试着右移开始位置
i
,判断当前的和sum
是否还大于等于target
,如果是的,就继续右移i
并更新res
;此时的sum
更新只需要减去刚刚移出滑动窗口的数值即可。
最后,如果 res = INT_MAX
,说明没有合适的连续子数组,返回 0
;否则返回 res
。
实现代码
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
int l = 0;
int res = INT_MAX;
int sum = 0;
for (int r = 0; r < n; ++r) {
sum += nums[r];
while (sum >= target) {
sum -= nums[l];
res = min(res, r - l + 1);
++l;
}
}
return res == INT_MAX ? 0 : res;
}
};
复杂度分析
时间复杂度:
O
(
n
)
O(n)
O(n),
n
n
n 为数组的长度。指针 l
和 r
最多各移动 n
次。
空间复杂度: O ( 1 ) O(1) O(1)。
写在最后
如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。
如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。
最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。