滑动窗口问题记录

对于字符串或者数组,找到一个连续的区间,这个区间满足一定的条件。这样的问题就使用滑动窗口来解决,滑动窗口,从某种意义上属于动态规划算法,也使用了双指针。

滑动窗口的关键是确定窗口的两个边沿什么时候移动,什么条件下移动。一般情况下,窗口右边沿是一直向前移动,在移动的过程中根据判断条件来决定左边沿是不是需要移动。

1最小覆盖字符串

76. 最小覆盖子串 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    string minWindow(string s, string t) {
        //找一个范围,字符串或者数组,这样的问题,使用滑动窗口
        //滑动窗口,关键是窗口的两个边沿什么时候移动
        //一般情况下是,一个边沿直接移动
        //另外一个在特定条件下移动
        //1、首先计算t字符串每个字符出现的次数
        //2、然后遍历s字符串,看计数,然后增加count,移动右边沿
        //3、什么时候移动左边沿呢,count和t的长度相同的时候,这个字符串就是一个预期的结果
        for (char oneC : t) {
            tCharCount[oneC]++;
        }

        int left = 0;
        int right = 0;
        for (right = 0; right < s.size(); right++) {
            sCharCount[s[right]]++;
            
            //为什么是<=,而不是<,因为sCharCount[s[right]]在上边已经++了
            if (sCharCount[s[right]] <= tCharCount[s[right]]) {
                count++;
            }

            while (sCharCount[s[left]] > tCharCount[s[left]]) {
                sCharCount[s[left]]--;
                left++;
            }

            if (count == t.size()) {
                if (ret.empty() || right - left + 1 < ret.size()) {
                    ret = s.substr(left, right - left + 1);
                }
            }
        }
        return ret;
    }

    int tCharCount[123] = {0};
    int sCharCount[123] = {0};
    int count = 0;
    std::string ret = "";
};

2无重复字符的最长子串

3. 无重复字符的最长子串 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        //最基本的方法
        //长度从大到小遍历字符串,看是不是有重复,有重复继续进行
        //没有重复直接返回

        //滑动窗口
        //右边沿直接滑动
        //用map保存字符所在的索引,如果已经存在了,说明重复了,移动left
        
        int ret = 0;
        int size = s.size();
        int left = 0;
        int right = 0;
        std::map<char, int> charIndex;
        for (; right < size; right++) {
          if (charIndex.find(s[right]) != charIndex.end()) {
            //这个判断条件很容易忘
            if (left < charIndex[s[right]] + 1) {
              left = charIndex[s[right]] + 1;
            }

          }
          //这行很容易忘
          charIndex[s[right]] = right;
          
          ret = (right - left + 1) > ret ? (right - left + 1) : ret;
        }
        return ret;
    }
};

3无重复字符的最长子串

3. 无重复字符的最长子串 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        //有边沿一直向前走
        //用一个sum记录和
        //当和大于等于target,移动left
        //ret初始值初始化为0
        int len = nums.size();
        int left = 0;
        int right = 0;
        int sum = 0;
        int ret = 1000000;
        for (; right < len; right++) {
            sum += nums[right];
            // >= 而不是 >,因为结果都是在这里计算的
            while (sum >= target) {
                ret = right - left + 1 < ret ? right - left + 1 : ret;
                sum -= nums[left];
                left++;
            }
        }

        return ret == 1000000 ? 0 : ret;
    }
};
相关推荐
不会代码的小猴1 小时前
C++的第十二天笔记
开发语言·c++·笔记
橘子真甜~1 小时前
C/C++ Linux网络编程10 - http协议
linux·服务器·网络·c++·网络协议·http
蜗牛love天空2 小时前
bfs广度优先搜索-二叉树遍历
c++
刘家炫2 小时前
C++ 中的模版元编程
c++·现代c++·模版元编程
十五年专注C++开发2 小时前
async_simple:一个轻量级C++异步协程框架
开发语言·网络·c++·boost·asio
2401_861277553 小时前
func(int* num)的实现是*num=2或者int a=3,num=&a都可以吗
c语言·c++
繁华似锦respect3 小时前
lambda表达式中的循环引用问题详解
java·开发语言·c++·单例模式·设计模式·哈希算法·散列表
我要升天!3 小时前
QT -- 网络编程
c语言·开发语言·网络·c++·qt
闻缺陷则喜何志丹4 小时前
【计算几何 矢量】2280. 表示一个折线图的最少线段数|1681
c++·数学·计算几何·矢量