每天一道LeetCode-----给定字符串s和字符数组words,在s中找到words出现的位置,words内部字符串顺序无要求
生活随笔
收集整理的這篇文章主要介紹了
每天一道LeetCode-----给定字符串s和字符数组words,在s中找到words出现的位置,words内部字符串顺序无要求
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Substring with Concatenation of All Words
原題鏈接Substring with Concatenation of All Words
題目意思是給定字符串s和字符數(shù)組words,在s中尋找words出現(xiàn)的位置,words內(nèi)部的字符串順序沒有要求
此問題可以直接順序搜索,假設(shè)s的長度為m,words的長度為n,words中每個單詞的長度為w,復(fù)雜度是O((m-n*w)*n),需要利用兩個unordered_map<string,int>,一個記錄每個單詞總共需要多少個,一個記錄當(dāng)前遍歷到的單詞數(shù),如果遇到不在words中的單詞,就break從下一個開始找
另一種方法是使用滑動窗口,也是利用兩個unordered_map<string, int>。原理是當(dāng)不匹配是移動起始點,每一移動w個距離。不匹配有兩種情況
舉個例子,
s = "barfoobarfoothebar"; words = ["bar","bar","foo","the"];unordered_map<string, int> counts; /** 記錄每個單詞需要的次數(shù)* bar foo the* 2 1 1*/unordered_map<string, int> seen; /** 記錄當(dāng)前找到的單詞數(shù)* bar foo the* 0 0 0*/int count; /* 記錄當(dāng)前找到的單詞數(shù),0,目標(biāo)大小為words的大小,4 */int startIndex; /* 開始位置,0,找到就把它添加到結(jié)果的vector中 *//*1. 從s起點開始找,每3一判斷,第一個bar,"bar"是要找的單詞(在counts中),給seen對應(yīng)為加一,此時seen["bar"]=1, count=1;2. 接著找第二個單詞"foo",也在counts中,給seen對應(yīng)位加一,此時seen["foo"]=1, count=2;3. 繼續(xù)找"bar",也在counts中,給seen加一,此時seen["bar"]=2,count=3;4. 繼續(xù)找"foo",也在counts中,給seen加一,此時seen["foo"]=2,但是counts["foo"]=1,表示"foo"只需要一個,此時不滿足條件,移動1. 從startIndex開始刪除單詞,直到找到第一個"foo"2. 刪掉"bar",此時seen["bar"]=1,count=1,startIndex=0+3=3;3. 刪掉"foo",此時seen["foo"]=1,不改變count,因為當(dāng)不滿足時,沒有增加count,startIndex=6;4. 找到第一個"foo"了,繼續(xù)查找單詞5. 繼續(xù)找"the",在counts中,給seen加一,此時seen["the"]=1,count=26. ...7. 最終找到count==n,將startIndex=6添加到結(jié)果中8. 再右移一個單詞,刪掉"bar",此時seen["bar"]=1,count=3,startIndex=99. 繼續(xù)尋找10. ...11. 遇到單詞"abc",不在counts中,重置seen,count,startIndex12. 繼續(xù)尋找13. ...14. 結(jié)束*/代碼如下
class Solution { public:vector<int> findSubstring(string s, vector<string>& words) {vector<int> res;if(s.size() == 0 || words.size() == 0)return res;unordered_map<string, int> dict;for(auto &str : words)++dict[str];int n = s.size();int cnt = words.size();int wl = words[0].size();/* * 每個單詞長度為wl,那么只需要循環(huán)wl次,每次移動wl個為* 0, wl, 2*wl, 3*wl ...* 1, 1+wl, 1+2*wl, 1+3*wl...* 2, 2+wl, 2+2*wl, 2+3*wl...* ...*/for(int i = 0; i < wl; ++i){int left = i;int count = 0;unordered_map<string, int> tdict; //seen/* 每次移動wl個 */for(int j = i; j <= n - wl; j+=wl){string str = s.substr(j, wl);/* 如果是需要的單詞,就添加到seen中 */if(dict.count(str)){tdict[str]++;/* 如果已經(jīng)不需要了,就不用增加count */if (tdict[str] <= dict[str]) count++;else{/* 如果當(dāng)前這個單詞是多余的,超出了數(shù)量限制,就移動窗口 */while (tdict[str] > dict[str]) {string str1 = s.substr(left, wl);tdict[str1]--;/* 因為多余的那個單詞沒有增加count,所以也不需要減count */if (tdict[str1] < dict[str1]) count--;left += wl;}}/* 如果到所有,右移 */if (count == cnt) {res.push_back(left);// advance one wordtdict[s.substr(left, wl)]--;count--;left += wl;}}/* 不是需要的單詞,重置所有 */else{tdict.clear();count = 0;left = j + wl;}}}return res;} };啊啊啊啊下午的心情一點也不好-.-
總結(jié)
以上是生活随笔為你收集整理的每天一道LeetCode-----给定字符串s和字符数组words,在s中找到words出现的位置,words内部字符串顺序无要求的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: muduo网络库学习(八)事件驱动循环线
- 下一篇: muduo网络库学习(九)日志类Logg