Leetcode——76. 最小覆盖子串

概述

题目连接

  • 注意:要求时间复杂度为 O ( n ) O(n) O(n)

分析

要求 O ( n ) O(n) O(n),并且结果也是一个连续的字符串,所以考虑使用双指针进行区间搜索

思路

  • 滑动窗口思路?
    • 首先固定左边界,然后右边界开始向右滑动向窗口中加入元素
    • 当所有所需的字符加入窗口后,此时右边界是最小的,但是左边界不一定,所以可以移动左边界,将字符移出去的同时继续使窗口满足条件
    • 直到因为左边界移动导致该窗口不满足条件,则停止移动左边界,继续移动右边界
    • 重复以上行为,直到右边界到达最后位置

代码

class Solution {
public:
    string minWindow(string s, string t) {
        // 前置处理,用来判断窗口内是否包含所有字符
        unordered_map<char,int> unordered_map_char_to_int;
        for (auto p : t) 
            ++unordered_map_char_to_int[p];
    
        int size_s = s.size(), size_t = t.size();
        int l = 0;			// 记录目前窗口的左边位置
        int min_l = 0;		// 记录之前窗口的左边位置
        int min_size = size_s + 1;        	// 记录窗口大小
        int count = 0;          			// 记录是否包含所有字符
        // 窗口左边界不动,右边界滑动,直到包含所有所需字符后,再移动左边界目的是减小窗口
        for(int r = 0; r < size_s; ++r) {
            if (unordered_map_char_to_int[s[r]]-- > 0) {		// >0,说明t中的字符被包含 
                ++count;
                while (count == size_t) {       	// 窗口内包含t的所有字符
                    if (r - l + 1 < min_size) {		// 比较窗口大小
                        min_l = l;		// 记录新窗口
                        min_size = r - l + 1;
                    }
                    if (++unordered_map_char_to_int[s[l]] > 0) {	// 移动窗口
                        											// 注意大小判断: >0说明所需某个字符已经不存在窗口中,此时需要右侧开始移动
                        --count;										
                    }
                    ++l;	// 移动现在窗口左边界,尽可能减小窗口
                }
            }
        }
        return min_size > size_s ? "" : s.substr(min_l, min_size);
    }
};
  • 尽管for循环里面有while循环,但是最坏情况是 O ( 2 n ) O(2n) O(2n)

你可能感兴趣的:(c++,刷题,滑动窗口,双指针)