【Minimum Window】cpp
题目:
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).
For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC"
.
Note:
If there is no such window in S that covers all characters in T, return the emtpy string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
代码:
class Solution { public: string minWindow(string s, string t) { if (s.empty() && t.empty() ) return ""; if (s.size()<t.size()) return ""; const int ASCII_MAX = 256; // record how much times a char occurs in t int t_char_count[ASCII_MAX] = {0}; for ( int i=0; i<t.size(); ++i ) { t_char_count[(int)t[i]]++; } // record how much times a char occurs in s int s_char_count[ASCII_MAX] = {0}; // global min begin and end index for minimum interval int begin_min=-1, end_min=s.size(); // local min begin ( no need to record local min end ,because it is 'i' ) int begin = 0; int match_size = 0; for ( int i=0; i<s.size(); ++i ) { // current interval not match && current char in t if ( t_char_count[(int)s[i]]>0 ) { //cout << s[i] << ":" << t_char_count[s[i]] << endl; s_char_count[(int)s[i]]++; // if a char occurs more times in current interval s than in t, can not increase match_size if ( s_char_count[(int)s[i]]<=t_char_count[(int)s[i]] ) match_size++; } if ( match_size==t.size() ) { // move begin forward untill not match while ( begin<=i ) { // only address chars not in t if ( s_char_count[(int)s[begin]]>0 ) { if ( s_char_count[(int)s[begin]]-1<t_char_count[(int)s[begin]] ) { //cout << s_char_count[s[begin]] << endl; match_size--; break; } s_char_count[(int)s[begin]]--; } begin++; } s_char_count[(int)s[begin]]--; // update global min begin and end if ( end_min-begin_min > i-begin ) { end_min = i; begin_min = begin; } begin++; } } if( end_min-begin_min>s.size() ) return ""; return s.substr(begin_min,end_min-begin_min+1); } };
tips:
曾经以为这种题比较简答,实际上不带算法模板套路的题才是最费神的。
这道题一开始的思路是记录t中每个字符最左边到哪最右边到哪,然后再云云;这个想法不太靠谱。
如果是bruce force暴力解法,时间复杂度可以是O(n²)的:
1. 遍历每个位置,以每个位置为中心,往左右走,直到包含所有的元素,取最短的。
2. 取所有interval中最短的。
可以AC的解法思路如下:
1. 维护几个核心变量:
a)t中每个字符出现了几次(t_char_count)
b) s中当前区间里面,t中每个字符出现了几次(s_char_count)
c) s当前区间是否满足包含t(match_size)
2. 这道题思路很有趣:先找满足包含t的区间;一旦找到了这样的区间,再缩小这样的区间。
缩减区间的方法:后面的指针保持不动,前面的指针往后移动,直到match_size < t.size(),则证明当前区间已经是最小的满足条件的区间了。
3. 动态更新最小区间。
主要参考:
http://www.cnblogs.com/TenosDoIt/p/3461301.html
http://fisherlei.blogspot.sg/2012/12/leetcode-minimum-window-substring.html
============================================
第二次过这道题,静下心来码。
class Solution { public: string minWindow(string s, string t) { int t_counts[256] = {0}; int s_counts[256] = {0}; for ( int i=0; i<t.size(); ++i ) t_counts[(int)t[i]]++; int matchTime = 0; int begin = -1; int end = s.size(); int b = 0; for ( int i=0; i<s.size(); ++i ) { // only address character occurs in string t if ( t_counts[(int)s[i]]>0 ) { s_counts[(int)s[i]]++; // after s_count add one change matchTime if ( s_counts[(int)s[i]]<=t_counts[(int)s[i]] ) matchTime++; } // when there is a window, then minimisze it if ( matchTime==t.size() ) { while ( b<=i ) { // only address charatcers occurs in string t if ( s_counts[(int)s[b]]>0 ) { // if move over 'begin then 'can not keep window if ( s_counts[(int)s[b]]-1 < t_counts[(int)s[b]] ) { matchTime--; break; } s_counts[(int)s[b]]--; } b++; } if ( i-b < end-begin ) { begin = b; end = i; } s_counts[(int)s[b]]--; b++; } } if ( end-begin>s.size() ) return ""; return s.substr(begin, end-begin+1); } };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?