考察知识点:滑动窗口

题目分析:

可以通过使用动态的滑动窗口解决问题。首先left和right指向最开始,然后只让right向右移动,每遍历到一个需要的字符时就记录下来。当left和right之间的字符满足条件时,right指针不动,left向右移动,每次遍历到一个需要的字符时需要将相应的字符减一,看是否仍满足条件。直到不满足条件的前一个字符,就是这一次找到的最短的满足需求的字符串。

到这时还没有结束,因为还没有遍历完整个数组,右边可能还有更短的。所以让right继续向右走,直到遍历完整个数组为止。

所用编程语言:C++

#include <unordered_map>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param s string字符串 
     * @param t string字符串 
     * @return string字符串
     */
    bool meetConditions(unordered_map<char, int> &need, unordered_map<char, int> &window) {
        for (auto item: need) {
            if (item.second > window[item.first]) 
                return false;
        }
        return true;
    }
    string minWindow(string s, string t) {
        // write code here
        int left = 0, right = 0;
        int minLength = 0x3f3f3f3f;
        int start = 0;
        int size = s.size();
        unordered_map<char, int> need;
        unordered_map<char, int> window;
	  //记录需求
        for (auto &ch : t) 
            need[ch]++;
	//使用滑动窗口进行查找
        while (right < size) {
            char ch = s[right++];
            if (need[ch]) window[ch]++;
            while (meetConditions(need, window)) {
                if (right - left + 1 < minLength) {
                    minLength = right - left + 1;
                    start = left;
                }
                char ch = s[left++];
                if (need[ch]) window[ch]--;
            }
        }
        if (minLength != 0x3f3f3f3f) return s.substr(start, minLength);
        else return "";
    }
};

动态滑动窗口的代码模板:

该模板来自惊鸿只为卿

int left = 0,right =0;
while(right指针未越界){
  char ch = arr[right++];
  //右指针移动,更新窗口
  ...
  
  //窗口数据满足条件 对于固定窗口而言,就是窗口的大小>=固定值;对于动态窗口,就是从left出发,窗口不断扩充,第一次满足题意的位置
  while(窗口数据满足条件){
  	//记录或者更新全局数据
  	...
  	
  	//右指针不动,左指针开始移动一位
  	char tmp = arr[left++];
  	
  	//左指针移动,窗口缩小,更新窗口数据
  	...
  }
  //返回结果
  ...
}