并分析时间复杂度与空间复杂度。
题目来源:
微软等公司数据结构+算法面试100 题V0.1 版
http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html
分析:
等效为有一个长度为m的字符串,有容量为N的字符集{a,b,c...}构成,求包含字符集的最小子串。
使用set来保存已经存在的字符。
顺序移动子串的开始位置,将set清空,移动子串的结束位置,并将字符加入set,直至set中元素个数为N,表明当前子串已经包含完整字符集;
注意首尾相连,子串结束位置移动到最后后要折回。当子串长度大于当前已知最小长度时,就没必要继续向后移动了,可以直接移动子串的开始位置。
string FindMinSet(const string &str,const set<char> &cset) { cout<<str<<endl; string res; int str_len=str.length(); int set_size=cset.size(); if (str_len<set_size) return res; int minlen=str_len; int besti=0,bestj=0; for (int i=0;i<str_len;i++) { set<char> tempset; tempset.clear(); tempset.insert(str[i]); for(int j=(i+1)%str_len;j!=((i+minlen)%str_len);j=(j+1)%str_len) { tempset.insert(str[j]); if (tempset.size()==set_size) { int thislen=j-i; if(thislen<0) thislen+=str_len; if (thislen<minlen) { minlen=thislen; besti=i; bestj=j; } break; } } } if (besti<bestj) { res=str.substr(besti,bestj+1-besti); } else { res=str.substr(besti,str_len-besti)+str.substr(0,bestj+1); } cout<<"len="<<minlen<<" i="<<besti<<" j="<<bestj<<endl; cout<<res<<endl; return res; } //测试用例 void FindMinSet( ) { char cc[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n'}; set<char> cset; for(int i=0;i<sizeof(cc)/sizeof(char);i++) cset.insert(cc[i]); string str; srand(time(NULL)); for(int i=0;i<120;i++) str+=cc[rand()%(sizeof(cc)/sizeof(char))]; FindMinSet(str,cset); }