
本文详解如何使用优化的滑动窗口算法,高效求解长度为 k 且所有元素互异的子数组的最大和,重点修复频次统计与窗口收缩逻辑中的常见错误。
本文详解如何使用优化的滑动窗口算法,高效求解长度为 k 且所有元素互异的子数组的最大和,重点修复频次统计与窗口收缩逻辑中的常见错误。
在解决「固定长度、元素互异子数组的最大和」这类问题时,核心挑战在于实时、准确地判断当前滑动窗口内是否恰好包含 k 个互异元素。初学者常引入布尔标志(如 canIcount)来标记窗口合法性,但该方式极易因状态更新不及时而失效——例如当窗口中存在多个重复元素时,无法可靠判定何时恢复“合法”状态。
正确思路是:直接利用哈希表(字典)的键数量作为唯一性判据。因为 len(eleToFreq) == k 当且仅当当前窗口内恰好有 k 个不同元素(且窗口长度恒为 k),这比维护额外标志更鲁棒、更简洁。
以下为优化后的完整实现(基于 Python):
class Solution:
def maximumSubarraySum(self, nums: List[int], k: int) -> int:
sum_so_far = max_sum = 0
freq = {}
left = 0
for right, val in enumerate(nums):
# 扩展右边界:添加 nums[right]
freq[val] = freq.get(val, 0) + 1
sum_so_far += val
# 当窗口长度达到 k 时,检查并更新答案
if right >= k - 1:
# 仅当窗口内元素全部互异(即不同元素个数 = k)时更新最大和
if len(freq) == k:
max_sum = max(max_sum, sum_so_far)
# 收缩左边界:移除 nums[left]
left_val = nums[left]
if freq[left_val] == 1:
freq.pop(left_val)
else:
freq[left_val] -= 1
sum_so_far -= left_val
left += 1
return max_sum✅ 关键修正点说明:
- 去标志化:摒弃易错的 canIcount 标志,改用 len(freq) == k 直接、精确判断窗口合法性;
- 窗口收缩逻辑修正:原代码中 if eleToFreq[a[i]] >= 1 会导致空键访问或逻辑错误;正确做法是先检查频次是否为 1(需 pop),否则减 1;
- 结构精简:合并重复逻辑,使用 for ... enumerate 替代手动双指针 while 循环,提升可读性与 Pythonic 风格;
- 边界处理简化:无需预先 if len(set(nums))
⚠️ 注意事项:
- 时间复杂度为 O(n),每个元素最多被访问两次(入窗 + 出窗);空间复杂度为 O(min(k, n)),由哈希表存储的最多 k 个不同元素决定;
- 切勿在收缩时使用 del freq[left_val] 而不检查存在性,应统一用 pop() 或条件判断;
- 若题目要求返回子数组而非和,可在 len(freq) == k 时记录 left 和 right 下标。
该解法兼顾正确性、简洁性与工程实践性,是滑动窗口处理“定长+去重”约束的经典范式。










