问题:一个字符串S(临时仅仅考虑小写字母),选择S中包括26种英文字母的最短子串。假设不包括则返回空字符
分析:双指针,动态维护一个区间。尾指针不断往后扫,当扫到有一个窗体包括了全部26种英文字母的字符串后。再收缩头指针。直到不能再收缩为止。最后记录全部可能的情况中窗体最小的。
代码演示样例:
#include <algorithm> #include <string> #include <iostream> using namespace std; const int UPPERALPHA_MAX = 26; class Solution { public: int appeared_count[UPPERALPHA_MAX]; public: //推断是否已找到包括26种英文字母的字符串 bool ContainAllAlpha(){ for(int i=0;i<26;i++){ if(appeared_count[i]<=0) return false; } return true; } //寻找符合条件的最小子串 string minWindow(string S) { if (S.empty()) return ""; if (S.size() < 26) return ""; fill(appeared_count, appeared_count + UPPERALPHA_MAX, 0); size_t minWidth = INT_MAX, min_start = 0; // 窗体大小,起点 int wnd_start = 0; //尾指针不断往后扫 for (size_t wnd_end = 0; wnd_end < S.size(); wnd_end++) { appeared_count[S[wnd_end]-'a']++;//统计当前各英文字母出现的次数 //当ContainAllAlpha()第一次为true后,其后的推断均为ture,后面程序执行的目的是找出最短的子串 if(ContainAllAlpha()){ //假设为true则包括了全部的26个英文字母 while(true){ //假设反复出现了,能够后移 if(appeared_count[S[wnd_start]-'a']>1){ appeared_count[S[wnd_start]-'a']--; wnd_start++; } else //仅仅出现了一次,停止后移 break; } //找出最短子串,更新最短长度,和最短长度的起点 if (minWidth > (wnd_end - wnd_start + 1)) { minWidth = wnd_end - wnd_start + 1; min_start = wnd_start; } } } if(minWidth!=INT_MAX) return S.substr(min_start, minWidth); else return ""; } }; int main(){ string s="aabcdefghhhiijkijkjkijkkklmnopqrstuvzzzwxyzzcbabcdefghijklmnopqrstuvwxxyz"; Solution solution; cout<<solution.minWindow(s)<<endl; }
输出结果为:abcdefghijklmnopqrstuvwxxyz
类似题目链接点击打开链接