力扣017_最小覆盖字串题解----C++

news/2025/2/2 11:59:45 标签: leetcode, 算法, 职场和发展

题目描述

  1. 我们可以用滑动窗口的思想解决这个问题。在滑动窗口类型的问题中都会有两个指针,一个用于「延伸」现有窗口的 r 指针,和一个用于「收缩」窗口的 l 指针。在任意时刻,只有一个指针运动,而另一个保持静止。我们在 s 上滑动窗口,通过移动 r 指针不断扩张窗口。当窗口包含 t 全部所需的字符后,如果能收缩,我们就收缩窗口直到得到最小窗口。、
  2. 如何判断当前的窗口包含所有 t 所需的字符呢?我们可以用一个哈希表表示 t 中所有的字符以及它们的个数,用一个哈希表动态维护窗口中所有的字符以及它们的个数,如果这个动态表中包含 t 的哈希表中的所有字符,并且对应的个数都大于或等于t 的哈希表中各个字符的个数,那么当前的窗口是「可行」的。

假设这是我们对应的是s和t

创建unordered_map<char,int> hs,ht

我们定义两个指针,作为遍历s的窗口,再定义一个cnt作为窗口内的有效字符。

遍历s,用for循环,每循环一次r,把r指向的值存入到hs中,

 unordered_map<char,int> hs,ht;
        string ans;
        for(auto &c:t) ht[c]++; 
        int l=0,r=0,cnt=0; //l为窗口的左边界,r为窗口的右边界
        for(;r<s.size();r++){ //每次循环右边界右移一次
            hs[s[r]]++;

此时有两种情况,当hs[s[r]]<=ht[s[r]] ,cnt++。

如果hs[s[l]]>ht[s[l]],说明hs里面已经存在两个相同的有效值了,如下图

ht:ABA,cnt=2 因为我们要找的是最小覆盖字串,且包含了A有效字符,所有这个时候我们的左窗口右移,并且减去一个A 

while(hs[s[l]]>ht[s[l]]){ //这个语句会右移左边界,比如这个边界字符不在t里,
                hs[s[l]]--;           //或者符合条件的边界值在后面又增加了一个且和左边界值相同,那么就可以右移左边界
                l++;

一次次的循环如下 

当我们的cnt 有效字符等于t.size()的时候,也就是这个窗口包含了t字符串的所有。

 if(cnt==t.size()){ //有效字符等于字符串t的长度,我们可以放入答案;
                if(ans.empty()||r-l+1<ans.size()) ans=s.substr(l,r-l+1);或者对比前窗口的大小和当前的大小,然后决定是否更新ans。
            }

如下即为全部的代码

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char,int> hs,ht;
        string ans;
        for(auto &c:t) ht[c]++; 
        int l=0,r=0,cnt=0; //l为窗口的左边界,r为窗口的右边界
        for(;r<s.size();r++){ //每次循环右边界右移一次
            hs[s[r]]++;
            if(hs[s[r]]<=ht[s[r]]) cnt++; //在找到第一个符合条件的窗口后,这个语句不会再运行了。
                                          //ps.该语句的作用是统计窗口内的有效字符
            //左边界右移                              
            while(hs[s[l]]>ht[s[l]]){ //这个语句会右移左边界,比如这个边界字符不在t里,
                hs[s[l]]--;           //或者符合条件的边界值在后面又增加了一个且和左边界值相同,那么就可以右移左边界
                l++;
            }
            if(cnt==t.size()){ //有效字符等于字符串t的长度,我们可以放入答案;或者对比前窗口的大小和当前的大小,然后决定是否更新ans。
               if(ans.empty()||r-l+1<ans.size()) ans=s.substr(l,r-l+1); 对比前窗口的大小和当前的大小,然后决定是否更新ans。
            }
        }
        return ans;
    }
};


http://www.niftyadmin.cn/n/5840042.html

相关文章

39. I2C实验

一、IIC协议详解 1、ALPHA开发板上有个AP3216C&#xff0c;这是一个IIC接口的器件&#xff0c;这是一个环境光传感器。AP3216C连接到了I2C1上: I2C1_SCL: 使用的是UART4_TXD这个IO&#xff0c;复用位ALT2 I2C1_SDA: 使用的是UART4_RXD这个IO。复用为ALT2 2、I2C分为SCL和SDA&…

自制虚拟机(C/C++)(二、分析引导扇区,虚拟机读二进制文件img软盘)

先修复上一次的bug&#xff0c;添加新指令&#xff0c;并增加图形界面 #include <graphics.h> #include <conio.h> #include <windows.h> #include <commdlg.h> #include <iostream> #include <fstream> #include <sstream> #inclu…

6 Flink 状态管理

6 Flink 状态管理 1. State-Keyed State2. State-Operator State3. Broadcast State 我们前面写的 wordcount 的例子&#xff0c;没有包含状态管理。如果一个task在处理过程中挂掉了&#xff0c;那么它在内存中的状态都会丢失&#xff0c;所有的数据都需要重新计算。从容错和消…

gentoo 中更改$PS1

现象&#xff1a;gentoo linux Xfce桌面&#xff0c;Terminal 终端&#xff0c;当进入很深的目录时&#xff0c;终端提示符会很长&#xff0c;不方便。如下图所示&#xff1a; 故需要修改$PS1 gentoo 默认的 PS1 在 /etc/bash/bashrc .d/10-gentoo-color.bash中定义&a…

洛谷 P10289 [GESP样题 八级] 小杨的旅游 C++ 完整题解

一、题目链接 P10289 [GESP样题 八级] 小杨的旅游 - 洛谷 二、题目大意 n个节点之间有n - 1条边&#xff0c;其中k个节点是传送门&#xff0c;任意两个传送门之间可以 以0单位地时间相互到达。问从u到v至少需要多少时间&#xff1f; 三、解题思路 输入不必多讲。 cin >> …

DeepSeek本地部署(windows)

一、下载并安装Ollama 1.下载Ollama Ollama官网:Ollama 点击"Download",会跳转至下载页面。 点击"Download for Windows"。会跳转Github进行下载,如下载速度过慢,可在浏览器安装GitHub加速插件。 2.安装Ollama 双击下载的安装文件,点击"Inst…

GPG格式介绍:什么是GPG?如何加密和解密?

什么是GPG&#xff1f; GPG&#xff08;GNU Privacy Guard&#xff09;是一种开源的加密工具&#xff0c;它是PGP&#xff08;Pretty Good Privacy&#xff09;的实现。GPG主要用于加密数据、创建数字签名以及密钥管理。它基于公钥加密和私钥解密的原理&#xff0c;能有效地保…

Java线程认识和Object的一些方法ObjectMonitor

专栏系列文章地址&#xff1a;https://blog.csdn.net/qq_26437925/article/details/145290162 本文目标&#xff1a; 要对Java线程有整体了解&#xff0c;深入认识到里面的一些方法和Object对象方法的区别。认识到Java对象的ObjectMonitor&#xff0c;这有助于后面的Synchron…