滑动窗口与前缀和:高效解决最短子数组问题

发布时间:2026/10/31 21:38:05
滑动窗口与前缀和:高效解决最短子数组问题 1. 问题背景与核心思路这道题目来自力扣LeetCode的LCR 008题要求在一个正整数数组中找到和大于等于给定target的最短连续子数组。这类子数组求和问题在实际开发中非常常见比如电商平台需要分析用户连续浏览时长、广告系统要计算连续曝光量等场景。我最初尝试暴力解法时发现时间复杂度高达O(n²)对于大数据量完全不可行。经过研究发现前缀和滑动窗口的组合能完美解决这个问题将复杂度降到O(n)。下面分享我的完整解题思路和优化过程。2. 前缀和原理与应用2.1 前缀和基础概念前缀和的核心思想是通过预处理构建一个前缀和数组prefix其中prefix[i]表示原数组前i个元素的和。例如原数组[2,3,1,2,4,3] 前缀和[0,2,5,6,8,12,15]注意前缀和数组通常会在开头添加一个0这是为了方便计算任意子数组和。子数组nums[i..j]的和可以表示为prefix[j1] - prefix[i]。关键技巧前缀和数组长度比原数组大1第一个元素固定为0。这个设计让边界条件处理变得统一。2.2 前缀和解法的实现使用前缀和可以直接写出解法def minSubArrayLen(target, nums): n len(nums) prefix [0] * (n 1) for i in range(n): prefix[i1] prefix[i] nums[i] res float(inf) for i in range(n1): for j in range(i1, n1): if prefix[j] - prefix[i] target: res min(res, j - i) break return res if res ! float(inf) else 0虽然这个解法比暴力法稍好内层循环可以提前break但时间复杂度仍然是O(n²)在力扣上会超时。3. 滑动窗口优化方案3.1 滑动窗口算法原理滑动窗口通过维护一个动态的窗口[left, right]来避免重复计算。当窗口和小于target时扩大右边界大于等于时收缩左边界过程中记录最小长度。这个算法的精妙之处在于窗口永远保持有效性和≥target时才收缩每个元素最多被访问两次进入和离开窗口时间复杂度严格O(n)3.2 标准滑动窗口实现def minSubArrayLen(target, nums): left total 0 res float(inf) for right in range(len(nums)): total nums[right] while total target: res min(res, right - left 1) total - nums[left] left 1 return res if res ! float(inf) else 03.3 关键点解析窗口移动条件只有当窗口和≥target时才移动左指针确保不会漏掉更优解长度计算时机在while循环内更新结果保证每次得到的都是有效窗口边界处理使用float(inf)初始化结果最后处理无解情况4. 算法优化与变种4.1 提前终止优化当找到长度为1的子数组时可以直接返回因为不可能有更短的解if res 1: return 14.2 处理负数的变种如果数组包含负数滑动窗口会失效。这时需要结合前缀和单调队列from collections import deque def minSubArrayLen(target, nums): prefix [0] for num in nums: prefix.append(prefix[-1] num) dq deque() res float(inf) for i, curr in enumerate(prefix): while dq and curr - prefix[dq[0]] target: res min(res, i - dq.popleft()) while dq and curr prefix[dq[-1]]: dq.pop() dq.append(i) return res if res ! float(inf) else 05. 复杂度分析与对比方法时间复杂度空间复杂度适用场景暴力法O(n²)O(1)小数据量前缀和O(n²)O(n)需要频繁查询子数组和滑动窗口O(n)O(1)正数数组前缀和单调队列O(n)O(n)含负数的数组6. 实际应用案例6.1 视频广告投放假设需要找到连续观看时长超过30秒的最短视频片段用于广告插入。将每个镜头的时长作为数组元素用滑动窗口可以高效找出最佳插入点。6.2 金融风控监测在交易流水数据中快速定位异常交易时间段如短时间内累计金额超过阈值。前缀和方案支持实时计算任意时间段的交易总额。7. 常见错误与调试技巧窗口收缩过度确保在total target时才移动左指针# 错误示例 if total target: # 应该用while而不是if res min(res, right - left 1) total - nums[left] left 1初始化问题结果初始值要设为足够大res len(nums) 1 # 比float(inf)更直观空数组处理需要显式处理nums为空的情况if not nums: return 08. 扩展思考8.1 与Flink窗口的区别虽然都叫窗口但Flink的滑动窗口是批处理概念处理的是无限数据流上的固定时间/数量窗口。而算法中的滑动窗口是单次遍历数组的技术。8.2 多维扩展对于二维矩阵中的子矩阵求和问题可以扩展为二维前缀和# 构建二维前缀和 prefix [[0]*(n1) for _ in range(m1)] for i in range(1, m1): for j in range(1, n1): prefix[i][j] matrix[i-1][j-1] prefix[i-1][j] prefix[i][j-1] - prefix[i-1][j-1] # 计算子矩阵(row1,col1)到(row2,col2)的和 sum prefix[row21][col21] - prefix[row1][col21] - prefix[row21][col1] prefix[row1][col1]在实际项目中我发现这类算法问题往往需要根据具体业务场景进行调整。比如在实时系统中可能需要结合环形缓冲区来实现滑动窗口在处理超大数据时可以考虑分段处理结合多线程优化。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询