滑动窗口是一种常用的算法技巧,主要用于解决数组/字符串的子区间问题。以下是
C++ 中滑动窗口的通用模板:
基本模板
intslidingWindowTemplate(vector<int>& nums, int k) { int n = nums.size(); int left = 0, right = 0; // 窗口左右边界 int result = 0; // 存储结果 unordered_map<int, int> window; // 用于记录窗口内元素的状态 while (right < n) { // 扩大窗口,加入右边元素 int c = nums[right]; right++; window[c]++; // 更新窗口状态 // 判断是否需要收缩窗口 while (window needs shrink) { // 这里需要根据具体问题实现条件 // 缩小窗口,移除左边元素 int d = nums[left]; left++; window[d]--; // 更新窗口状态 } // 更新结果(根据具体问题可能需要放在不同位置) result = max(result, right - left); // 或其他计算方式 } return result; }
常见变体
1. 固定窗口大小
intfixedSlidingWindow(vector<int>& nums, int k) { int n = nums.size(); int sum = 0; // 计算初始窗口 for (int i = 0; i < k; i++) { sum += nums[i]; } int maxSum = sum; // 滑动窗口 for (int i = k; i < n; i++) { sum += nums[i] - nums[i - k]; // 加新元素,减旧元素 maxSum = max(maxSum, sum); } return maxSum; }
2. 可变窗口大小(求最大窗口)
intvariableMaxWindow(string s) { unordered_map<char, int> window; int left = 0, right = 0; int maxLen = 0; while (right < s.size()) { char c = s[right]; right++; window[c]++; // 当窗口内有重复字符时,收缩窗口 while (window[c] > 1) { char d = s[left]; left++; window[d]--; } maxLen = max(maxLen, right - left); } return maxLen; }
3. 可变窗口大小(求最小窗口)
string minWindow(string s, string t) { unordered_map<char, int> need, window; for (char c : t) need[c]++; int left = 0, right = 0; int valid = 0; // 记录满足条件的字符数 int start = 0, len = INT_MAX; while (right < s.size()) { char c = s[right]; right++; if (need.count(c)) { window[c]++; if (window[c] == need[c]) { valid++; } } // 当窗口满足条件时,尝试收缩窗口 while (valid == need.size()) { // 更新最小窗口 if (right - left < len) { start = left; len = right - left; } char d = s[left]; left++; if (need.count(d)) { if (window[d] == need[d]) { valid--; } window[d]--; } } } return len == INT_MAX ? "" : s.substr(start, len); }