【优选算法篇】一文读懂滑动窗口:动态调整范围的算法利器(上篇)

文章目录

须知

💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力!

👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗?别忘了点赞、收藏并分享给更多的小伙伴哦!你们的支持是我不断进步的动力!
🚀 分享给更多人:如果你觉得这篇文章对你有帮助,欢迎分享给更多对C++算法感兴趣的朋友,让我们一起进步!

 1. C++ 滑动窗口算法详解

1.1 滑动窗口算法重要性

 滑动窗口(Sliding Window)是一种高效的算法思想,广泛应用于数组和字符串问题,特别是涉及子数组、子字符串、窗口内统计等场景。它的重要性在于:

  1. 提升效率:通过动态调整窗口范围,避免暴力枚举所有可能的子区间,从而将时间复杂度从 O(N^2) 或更高优化到 O(N)
  2. 简化逻辑:滑动窗口提供了一个统一的框架,可以直观地处理许多问题,如最大/最小子数组和、子数组个数统计等。
  3. 实际应用广泛:在数据流、字符串处理、窗口内最值计算等领域具有广泛应用。

本文将通过简单的例题来讲解“同向双指针”算法的不同应用,以及如何在 C++ 中实现。同向双指针也称为“滑动窗口”。

1.2 什么是滑动窗口?

 滑动窗口是一种动态调整区间范围的算法。它将问题中的“窗口”定义为一段连续的子数组或子字符串,并通过增加或减少窗口的左右边界来动态计算结果。窗口的范围会随着问题的需求而“滑动”,从而优化问题求解过程。

窗口的两种典型类型:

  1. 固定窗口:窗口大小固定,通过滑动计算覆盖不同的区间。
  2. 可变窗口:窗口大小可变,根据条件动态调整范围。

1.3 核心思想

 滑动窗口的核心思想是:

通过一对指针(通常为左右指针 leftright),定义一个“窗口”,然后在窗口内进行动态计算。

实现步骤

  1. 初始化窗口:定义窗口的起点(left)和终点(right),一般初始为 0
  2. 扩展窗口:通过移动 right 指针扩展窗口,直到窗口内满足特定条件。
  3. 缩小窗口:当窗口满足条件时,移动 left 指针缩小窗口,同时更新结果。
  4. 重复上述过程:直到 right 指针遍历完整个数组或字符串。

关键点

  • 动态调整窗口的范围。
  • 记录窗口内的状态(如当前和、频率计数等)。
  • 根据问题需求判断何时更新结果。

1.4 滑动窗口的应用场景

  1. 求解固定长度的子数组/子字符串问题
    • 如最大或最小子数组和,最长不重复子字符串。
  2. 求解动态条件的区间问题
    • 如满足条件的最短子数组,窗口内的元素个数统计。
  3. 在线算法和数据流问题
    • 滑动窗口可以在数据流中实时计算指标。

 2. 滑动窗口的逻辑可以归纳为以下模板:

int slidingWindow(vector<int>& nums, int target)
{
    int left = 0, current_sum = 0, result = INT_MAX;
    for (int right = 0; right < nums.size(); ++right)
    {
        current_sum += nums[right];  // 扩展窗口
        while (current_sum >= target)// 符合条件,尝试缩小窗口
        {  
            result = min(result, right - left + 1);
            current_sum -= nums[left++];  // 移动左边界,缩小窗口
        }
    }
    return result == INT_MAX ? 0 : result;  // 如果没找到满足条件的子数组返回 0
}

 3. 题目1:长度最小的子数组

题目链接:209. 长度最小的子数组 - 力扣(LeetCode)

题目描述:

3.1 算法思路: 

3.1.1 初始化变量
  • startend
    • 两个指针分别表示滑动窗口的左边界和右边界。
    • start 用于缩小窗口,end 用于扩展窗口。
  • ret
    • 记录满足条件的最小子数组长度,初始化为 INT_MAX(一个很大的值)。
  • sum
    • 维护当前窗口内元素的总和。

3.1.2 扩展窗口

通过 for 循环移动右边界 end

  • 每次加入 nums[end]sum 中,表示将当前元素纳入窗口。
  • 目的:不断扩大窗口直到窗口内的和满足条件。

3.1.3 缩小窗口
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值