滑动窗口是处理字符串和数组问题的经典方案。
窗口滑动的思想:顾名思义,滑动窗口就是滑动的窗口,在字符串上从左往右滑动,直到串尾。滑动窗口的窗口长度是动态变化的,所以用两个指针来维护。
滑动的方向:串首—->串尾。
窗口的大小控制:何时改变i j的值。
窗口滑动实现的数据结构:高效查找,可使用hash。
- 反射弧
1、反转字符串
void reverseString(vector<char>& s) {int left = 0;int right = s.size() - 1;while (left < right) {swap(s[left], s[right]);left++;right--;}// reverse(s.begin(), s.end()); // 使用库函数}
2、反转字符串II
给定一个字符串 s 和一个整数 k,你需要对从字符串开头算起的每隔 2k 个字符的前 k 个字符进行反转。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
note:
其实在遍历字符串的过程中,只要让 i += (2 k),i 每次移动 2 k 就可以了,然后判断是否需要有反转的区间。
string reverseStr(string s, int k) {for (int i = 0; i < s.size(); i += (2 * k)) {// 1. 每隔 2k 个字符的前 k 个字符进行反转// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符if (i + k <= s.size()) {reverse(s.begin() + i, s.begin() + i + k );continue;}// 3. 剩余字符少于 k 个,则将剩余字符全部反转。reverse(s.begin() + i, s.begin() + s.size());}return s;}
3、904水果成篮
// 904.水果成篮int totalFruit(vector<int>& tree, int K) {int n = tree.size();int left = 0;int right = 0;vector<int> mp(n, 0);int ans = INT_MIN;int count = 0;while (right < n) {if (mp[tree[right]] == 0) {count++;}mp[tree[right]]++;while (count > K) {mp[tree[left]]--;if (mp[tree[left]] == 0) {count--;}left++;}right++;ans = max(ans, right - left);}return ans;}// 795. 区间子数组个数, 注意K的取值int numSubarrayBoundedMax(vector<int>& nums, int left, int right) {return maxK(nums, right) - maxK(nums, left - 1);}int maxK(vector<int>& nums, int k) {int left = 0;int right = 0;int ans = 0;int n = nums.size();while (right < n) {if (nums[right] > k) {right++;left = right;continue;}right++;ans += right - left;}return ans;}// 992. K 个不同整数的子数组int subarraysWithKDistinct(vector<int>& nums, int k) {return maxK(nums, k) - maxK(nums, k - 1);}int maxK(vector<int>& nums, int k){vector<int> mp(nums.size() + 1, 0);int left = 0;int right = 0;int count = 0;int res = 0;while (right < nums.size()) {if (mp[nums[right]] == 0) {count++;}mp[nums[right]]++;right++;while (count > k) {mp[nums[left]]--;if (mp[nums[left]] == 0) {count--;}left++;}res += right - left; // 为什么用子数组的长度即right - left来表示增加的子数组个数呢?}return res;}/*为什么可以新用子数组的长度即right - left来表示增加的子数组个数呢?可以借鉴动态规划的思想,举个例子就好理解了:当满足条件的子数组从[A,B,C]增加到[A,B,C,D]时,新子数组的长度为4,同时增加的子数组为[D],[C,D],[B,C,D],[A,B,C,D]也为4。*/
