【Minimum Window】cpp
2015-06-08 15:13
337 查看
题目:
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 =
T =
Minimum window is
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.
代码:
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. 动态更新最小区间。
主要参考:
/article/4879682.html
http://fisherlei.blogspot.sg/2012/12/leetcode-minimum-window-substring.html
============================================
第二次过这道题,静下心来码。
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. 动态更新最小区间。
主要参考:
/article/4879682.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); } };
相关文章推荐
- 关于C#中调用C++编写的DLL(非托管的DLL)的实现和问题记录
- C++ ofstream和ifstream详细用法
- 用c++写的数字阅读软件!
- VC++ 里面的_tmain 和 main的区别
- C++ this 指针 浅析
- C++9.5 vector/list/queue容器的区别与选用
- 一个同学的c++的故事(推测c++的由来)(一)
- 面向对象程序设计-C++ Stream & Template & Exception【第十五次上课笔记】
- NYOJ 53 无聊的小明
- C++位操作符
- C++ Primer 学习笔记_2_快速入门(续)
- C++ Primer 学习笔记_1_快速入门
- C++ Primer 学习笔记_5_变量和基本类型(续2)
- MySQL的C++封装
- C++ Primer 学习笔记_4_变量和基本类型(续1)
- C++ Primer 学习笔记_3_变量和基本类型
- c/c++ define用法
- 代码,用c++实现线性链表
- 代码,用c++实现线性链表
- C++中使用指针访问类私有变量