You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters.
For example, given:
S:
"barfoothefoobarman"
L:
["foo", "bar"]
You should return the indices:
[0,9]
.(order does not matter).
------------------------------------------------------------------------
use two maps to count occurrences of all patterns, iterate through S to check if each word in L exactly occurs once in current part of S
solution is from internet
this is a boring and tasteless question
time and space complexity?
notice the conversion (int)S.size() in for loop
class Solution { public: vector<int> findSubstring(string S, vector<string> &L) { map<string, int> words; map<string, int> curStr; for(int i = 0; i < L.size(); ++i) ++words[L.at(i)]; int N = L.size(); vector<int> ret; if(N <= 0) return ret; int M = L.at(0).size(); for(int i = 0; i <= (int)S.size()-N*M; ++i) { curStr.clear(); int j = 0; for(j = 0; j < N; ++j) { string w = S.substr(i+j*M, M); if(words.find(w) == words.end()) break; ++curStr[w]; if(curStr[w] > words[w]) break; } if(j == N) ret.push_back(i); } return ret; } };Update on Sep-11-2014
The idea is similar to Longest Substring Without Repeating Characters. Each word has the same length and can be seen as a unique(or not) character.
A slightly different implementation is it can re-assign a new map at the beginning of outer loop.
Update on Feb-17-2015
COME_BACK
inner loop里的算法
#1 如果找不到当前word,重新设置map和start,重新开始
#2 如果找到且数量 > 0
#3 如果找到且数量 == 0: 从start开始pop旧的word,直到找到当前的为止
因为所有词为无序,不用保证维护当前的数组, 如
1 - 2 -..........3 - 2 - 1, 假设扫到3时已经找到所有的词
class Solution { public: vector<int> findSubstring(string s, vector<string>& words) { unordered_map<string,int> dic; for (int i = 0; i < words.size(); i++) { if (dic.find(words[i]) == dic.end()) { dic[words[i]] = 1; }else { dic[words[i]]++; } } vector<int> rt; int wordLen = words[0].length(); for (int i = 0; i < wordLen; i++) { int start = i,count = 0; unordered_map<string,int> temp = dic; for (int j = i; j < s.length(); j += wordLen) { string word = s.substr(j,wordLen); if (temp.find(word) == temp.end()) { count = 0; temp = dic; start = j + wordLen; continue; }else if (temp[word] > 0) { temp[word]--; count++; if (count == words.size()) rt.push_back(start); }else if (temp[word] == 0) { while (true) { string begin = s.substr(start,wordLen); if (begin == word) { start += wordLen; if (count == words.size()) rt.push_back(start); break; } temp[begin]++; count--; start += wordLen; } } } } return rt; } };
Java, updated on Sep-25th-2018
3种情况:
1. map有单词且次数大于0
2. map有单词但次数等于0
3. map不包含单词
2和3可以揉成一个branch
class Solution { public List<Integer> findSubstring(String s, String[] words) { Map<String, Integer> map = getMap(words); List<Integer> rt = new ArrayList<>(); if (s.length() == 0 || words.length == 0) return rt; for (int i = 0; i < words[0].length(); i++) { rt.addAll(findSub(s, i, map, words[0].length(), words.length)); } return rt; } private List<Integer> findSub(String s, int i, Map<String, Integer> map, int len, int count) { List<Integer> rt = new ArrayList<>(); Map<String, Integer> local = new HashMap<>(map); int start = i; int tempCount = count; while (i < s.length() - len + 1) { String word = s.substring(i, i + len); if (local.containsKey(word) && local.get(word) > 0) { local.put(word, local.get(word) - 1); i += len; tempCount--; if (tempCount == 0) { rt.add(start); String old = s.substring(start, start + len); local.put(old, local.get(old) + 1); start += len; tempCount++; } }else { while (true) { String old = s.substring(start, start + len); if (old.equals(word)) { start += len; break; } local.put(old, local.get(old) + 1); start += len; tempCount++; } i += len; } } return rt; } private Map<String, Integer> getMap(String[] words) { Map<String, Integer> map = new HashMap<>(); for (String word : words) { map.put(word, map.getOrDefault(word, 0) + 1); } return map; } } }Combination Sum
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
- All numbers (including target) will be positive integers.
- Elements in a combination (a1, a2, � , ak) must be in non-descending order. (ie, a1 ? a2 ? � ? ak).
- The solution set must not contain duplicate combinations.
2,3,6,7
and target 7
,A solution set is:
[7]
[2, 2, 3]
-------------------------------------------------------------
combination
class Solution { public: void comb (vector<int> &candidates, int target,vector<vector<int> > &ret,vector<int> cur,int start) { if (target == 0) { ret.push_back(cur); }else { for (int i=start;i<candidates.size();i++) { if (target - candidates[i] >= 0) { vector<int> v = cur; // Attention here!!! v.push_back(candidates[i]); comb(candidates,target-candidates[i],ret,v,i); } } } } vector<vector<int> > combinationSum(vector<int> &candidates, int target) { // Start typing your C/C++ solution below // DO NOT write int main() function sort(candidates.begin(),candidates.end()); vector<vector<int> > ret; vector<int> cur; comb(candidates,target,ret,cur,0); return ret; } };
class Solution { public: void comb(vector<vector<int> > &rt, vector<int> &candidates, vector<int> cur, int target, int index) { if (target == 0) { rt.push_back(cur); return; } if (index >= candidates.size() || target < 0) return; comb(rt,candidates,cur,target,index + 1); cur.push_back(candidates[index]); comb(rt,candidates,cur,target - candidates[index],index); } vector<vector<int>> combinationSum(vector<int>& candidates, int target) { sort(candidates.begin(),candidates.end()); vector<vector<int> > rt; vector<int> cur; comb(rt,candidates,cur,target,0); return rt; } };Permutations
Given a collection of numbers, return all possible permutations.
For example,
[1,2,3]
have the following permutations:[1,2,3]
, [1,3,2]
, [2,1,3]
, [2,3,1]
, [3,1,2]
, and [3,2,1]
.--------------------------------------------------------------------
class Solution { public: void per (vector<int> num,vector<int> cur,vector<vector<int> > &ret) { if (num.size() == 0) { ret.push_back(cur); } for (int i=0;i<num.size();i++) { vector<int> v = cur; vector<int> w = num; v.push_back(w[i]); w.erase(w.begin()+i); per(w,v,ret); } } vector<vector<int> > permute(vector<int> &num) { // Start typing your C/C++ solution below // DO NOT write int main() function vector<vector<int> > ret; vector<int> cur; per(num,cur,ret); return ret; } };
#1 以index为分界线,来区分已经使用和未使用的集合(此条不一定为正确,需看代码)
#2 换句话说,每一个recursive call,都遍历所有未使用的数字确定在index(n次)
index = 0: 123, 213, 321
index = 1: 132, 231, 312
index = 2: 插入
class Solution { public: void swap(vector<int> &nums,int i,int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } void per(vector<vector<int> > &rt, vector<int> &nums, int index) { if (nums.size() == index) { rt.push_back(nums); return; } for (int i = index; i < nums.size(); i++) { swap(nums,i,index); per(rt,nums,index + 1); swap(nums,i,index); // 此行可以不加,结果同样正确,因为每一次都会确定一个数 } } vector<vector<int>> permute(vector<int>& nums) { vector<vector<int> > rt; per(rt,nums,0); return rt; } };
No comments:
Post a Comment