一.题目链接:https://leetcode.com/problems/minimum-window-substring/

二.题目大意:

 给定两个字符串S和T,要求从S中找出包含T中所有字母的最短子串,同时要求时间复杂度为O(n)。

三.题解:

这道看上去和https://leetcode.com/problems/longest-substring-without-repeating-characters最长不重复子序列类似,似乎都可以利用滑窗法来解决(当然,此处的窗口大小必然是动态的,不固定的)。然而不同的是,S中的字符可能包含T中不存在的字符,也就是说:在滑窗构建的过程中(遍历S的过程中),会遇到两种情况,当前字符不是T中的字符和当前字符是T中的字符。那么如何构建滑窗呢?具体如下:

(1)我们设置两个指针left和right,分别表示滑窗的两端。哈希表_map用于存储T中出现的字符以及相应的个数。cnt用于统计目前滑窗中出现的T中的字符的个数。

(2)right指针不停的向右移动,并且判断此处的字符是否是T中的字符,是的话,计数器cnt加1,同时_map中相应的字符对应的次数减去1。当cnt的数值与T的长度相同时,表示我们已经构造完成了一个符合条件的滑窗了。

(3)由于,整个S中可能存在多个符合条件的滑窗,所以当我们找到一个符合条件的滑窗时,需要记录相应的长度和起始下标;然后再去构建下一个滑窗。

(4)如何构建下一个滑窗呢?此时,就需要操作左指针left了,将left向右移动,若left处的字符是T中的字符的话,则cnt减去1。相应的_map处的字符对应的次数加1,此时需要构建新的滑窗,再去操作right指针;重复这个过程直至遍历完S。如果left处的字符不是T中的字符的话,继续右移,知道遇到T中的字符。

实现代码如下:

class Solution {
public:
string minWindow(string S, string T) {
int s_len = S.size();
int t_len = T.size();
if(s_len == 0 || t_len == 0 || s_len < t_len)//特殊输入的处理
return "";
int cnt = 0;//用于统计当前滑动窗口内中包含T中的字符的个数
int len = INT_MAX;//此处我用的int的最小值,也可以用s_len + 1
int head = -1;//记录最终结果的初始位置
int left = 0, right = 0;//定义滑动窗口的两个边界
unordered_map<char,int> _map;//存储T中的字符及出现的次数
for(int i = 0; i < t_len; i++)//初始化哈希表_map
{
if(_map.find(T[i]) == _map.end())
_map.insert(pair<char,int>(T[i],1));
else
(_map.find(T[i])->second)++;
}
for(right = 0 ; right < s_len; right++)//移动右指针
{
if(_map.find(S[right]) != _map.end())//当窗口内部含有T中的字符时
{
_map[S[right]]--;//相应字符的此处减1
if(_map[S[right]] >= 0)//减1后如果次数大于等于0,说明我们已经满足一个字符了,所以cnt加1
cnt++;
while(cnt == t_len)//如果滑窗内已经包含所有T中的字符
{
if(right - left + 1 < len)//更新最小的情况
{
len = right - left + 1;
head = left;
}
if(_map.find(S[left]) != _map.end())//如果左指针处指的是T中的字符;如果不是T中的字符则继续左移
{
_map[S[left]]++;//相应处的字符的次数加1
if(_map[S[left]] > 0)//如果加1之后此处大于0了,说明需要这个字符(这个字符是唯一的),如果向右移动的话(舍去这个字符),cnt就会减1
cnt--;
//如果这个字符不是唯一的话,不需要操作
}
left++;//移动左指针,直到滑窗中不再包含T中的全部字符
}
}
}
return head == - 1 ?"" : S.substr(head,len);//head== -1相当于没找到符合条件的子序列 }
};

  

实际上,左指针移动时,相当于考虑了三种情况:left处的字符不是T中的字符、left处的字符是T中的字符且是唯一的、left处的字符是T中的字符但不是唯一的(滑窗中其他处还有这个字符,此时_map[S[left]]是小于等于0的)。

我们也可以把_map[S[i]]理解成还需要多少个S[i]字符。该算法的时间复杂度为O(N),空间复杂度为O(1),因为ASCII码的话,最多256个字符就行。

LeetCode——727.Minimum Window Subsequence的更多相关文章

  1. [LeetCode] 727. Minimum Window Subsequence 最小窗口序列

    Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequence of ...

  2. [LeetCode] 727. Minimum Window Subsequence 最小窗口子序列

    Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequenceof  ...

  3. LC 727. Minimum Window Subsequence 【lock,hard】

    Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequenceof  ...

  4. [LeetCode] Minimum Window Subsequence 最小窗口序列

    Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequence of ...

  5. [LeetCode] 76. Minimum Window Substring 最小窗口子串

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  6. [LeetCode] 76. Minimum Window Substring 解题思路

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  7. [Leetcode][JAVA] Minimum Window Substring

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  8. 【leetcode】Minimum Window Substring (hard) ★

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  9. Java for LeetCode 076 Minimum Window Substring

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

随机推荐

  1. hdu6129 Just Do It!

    多校时找规律做过... 题意,给你一个数列a[1], a[2], a[3], a[4], ... , a[n],操作一次后变为a[1], a[1] ^ a[2], a[1] ^ a[2] ^ a[3] ...

  2. pytoch word_language_model 代码阅读

    参考代码地址:https://github.com/pytorch/examples/tree/master/word_language_model /word_language_model/data ...

  3. 再次提供一个纯粹通过pl/sql解析json的方法。

    在github上面有一个叫pljson的项目,该项目就是用pl/sql 来解析json的. 项目地址:pljson(需翻|强),如果翻不了强的同学,我在国内克隆了一个副本,不定期同步更新 pljson ...

  4. 第8天【文件系统挂载、ext文件系统及read命令、Linux RAID、lvm应用】

    文件系统挂载与管理工具(01)_recv 文件系统管理: 将额外文件系统与根文件系统某现存的目录建立关联关系,进而使得此目录作为其他文件访问入口的行成为挂载: 解除此关联关系的过程 吧设备关联挂载点: ...

  5. vue-router beforeEach死循环

    vue中页面跳墙处理 页面跳墙中使用 vue-router中的 beforeEach的死循环问题 问题展现 import Router from 'vue-router' const router = ...

  6. vscode 快捷键

    ctrl+/   单行注释:// 若要多行注释://,先选中这些要注释的行,再按ctrl+/ shift+Alt+A 多行注释 撤销刚才的操作:Ctrl+Z 恢复刚才的操作:Ctrl+Shift+Z ...

  7. Python—字符串的操作

    字符串的操作 变量: 变量只能是 字母,数字或下划线的任意组合,但首个字符不能为数字,且不能有空格 以下关键字不能声明为变量: and ,as, assert, break ,class ,conti ...

  8. Linux目录结构 重要目录结构详细

    1.1 /etc/hosts ip地址与主机名(域名)的对应关系  解析主机名  ping www.baidu.com 解析成10.0.0.200 1.产品测试 2  用主机名互相访问 1.2 /et ...

  9. Xcode10 library not found for -lstdc++ 找不到问题

    在Xcode9上正常编译的项目,在Xcode10上编译可能会遇到如下错误: library not found library not found library not found for -lst ...

  10. 特殊场景Sql优化

    一.大表的大数据量修改 问题: 1.大量的行级锁,长时间阻塞   2.主从延时,大批数据不一致 解决方法: 分批次修改 二.大表的表结构修改 问题:长时间锁表 解决方法: 1.从库修改,主从切换,主库 ...