1. 滑动窗口算法精讲:从入门到精通
作为一名算法爱好者,我深知滑动窗口算法在解决子数组/子字符串问题中的重要性。今天我想和大家分享两道LeetCode经典题目(713和1358)的详细解析,希望能帮助初学者更好地掌握这一技巧。
滑动窗口算法本质上是一种双指针技巧,特别适合处理数组/字符串中的连续子序列问题。它的核心思想是维护一个窗口,通过调整窗口的左右边界来高效地解决问题,通常能将O(n²)的时间复杂度优化到O(n)。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 713题:乘积小于K的子数组解析
2.1 问题重述与理解
题目要求我们统计数组中所有乘积严格小于k的连续子数组的个数。以示例1为例:
- 输入:nums = [10,5,2,6], k = 100
- 输出:8
- 解释:符合条件的子数组有[10],[5],[2],[6],[10,5],[5,2],[2,6],[5,2,6]
关键点在于:
- 子数组必须是连续的
- 所有元素的乘积必须严格小于k
- 需要统计所有可能的子数组数量
2.2 算法思路详解
滑动窗口解法步骤如下:
- 初始化左指针left=0,结果ans=0,乘积mul=1
- 遍历数组,右指针i从0到n-1:
a. 将当前元素乘入mul
b. 当mul≥k时,从左开始除nums[left]并右移left
c. 每次循环结束时,ans增加i-left+1
核心逻辑在于:对于每个右边界i,以i结尾的符合条件的子数组数量就是窗口长度(i-left+1)
2.3 代码实现与逐行解析
cpp复制class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
if (k <= 1) return 0; // 特殊情况处理
int left = 0, ans = 0, mul = 1;
for (int i = 0; i < nums.size(); i++) {
mul *= nums[i]; // 扩展右边界
while (mul
