leetcode 76 - 最小覆盖子串[滑动窗口] Hard

题目: https://leetcode.cn/problems/minimum-window-substring/
程序目录结构如下,
程序目录结构
CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

project(minimum_window_substr)
set(CMAKE_CXX_STANDARD 20)
add_definitions(-g)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../include)
string(REPLACE ".cpp" "" file "main.cpp")
add_executable(${file}  "main.cpp")

main.cpp

#include "printer/printer.hpp"

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    string minWindow(string s, string t) {
        // chars 记录t中每个字符的数量
        vector<int> chars(128, 0);
        // flag表示每个字符是否在t中存在
        vector<bool> flag(128, false);

        for(int i=0; i<t.size(); ++i) {
            flag[t[i]] = true;
            ++chars[t[i]];
        }

        // 移动滑动窗口,不断更改统计数据
        // 统计窗口中字符的个数
        int cnt{0};
        // 滑动窗口的左栅栏
        int l{0};
        // 最终最小字符串的起始位置
        int min_l {0};
        // 最终最小字符串的长度,初始化为一个不可能达到的值,如果最后没有改变,
        // 就说明没有找到,
        // 否则最后改变了,小于这个值,就说明找到了
        int min_size {(int)s.size() + 1};
        // 从左向右扫描, 优先移动右窗口位置
        for(int r=0; r<s.size(); ++r) {
            // 说明s中的当前字符在t中存在
            if(flag[s[r]]) {
                // 注意统计的时候,只统计 t中的字符个数那么多次,多于t中的字符个数的,不计入cnt的统计范围内,cnt不++
                // 例如t中的a出现3次,那么而s中的a出现4次,那么cnt ++到3就不加了。
                // 但是 chars数组中的a的统计数还是要减,这样最终会减到-1 [3-4=-1]
                // 这个多出来的-1可以用来在向右滑动l的过程中使用,说明多统计了一次a,
                // 我们滑动l窗口的时候只有当++chars[a] > 0的时候才说明已经到达了a本身出现的次数,3次
                // 如果这个时候再看到char a,那就需要 -- cnt了,表示再向右滑动就会少一个字符a了 
                if(--chars[s[r]] >= 0) {
                    ++ cnt;
                }
                // 若目前滑动窗口中已经包含t的全部字符
                // 尝试将l右移,在不影响结果的情况下,获得最短子字符串
                while(cnt == t.size()) {
                    // 更新字符串起始位置和最小长度
                    if(r-l+1 < min_size) {
                        min_l = l;
                        min_size = r - l + 1;
                    }

                    if(flag[s[l]] && ++chars[s[l]]>0) {
                        -- cnt;
                    }

                    ++l;
                }
            }   
        }
        return min_size > s.size() ? "": s.substr(min_l, min_size);
    }
};

auto main(int argc, char** argv) -> int {
    Solution s;
    string source = "ADOBECODEBANC";
    string t = "ABC";
    auto res = s.minWindow(source, t);
    cout << "Source string: " << source << "\n";
    cout << "Dest string: " << t << "\n";
    cout << "Min window: " << res << "\n";
    return EXIT_SUCCESS;
}

程序输出如下,
程序输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值