1286. Iterator for Combination
问题:
设计一个组合指针类,通过给定组合元素characters,要求构成组合的大小combinationLength,实现以下方法
构造方法:CombinationIterator(string characters, int combinationLength)
返回下一个组合:next()
是否存在下一个组合:hasNext()
Example 1: Input ["CombinationIterator", "next", "hasNext", "next", "hasNext", "next", "hasNext"] [["abc", 2], [], [], [], [], [], []] Output [null, "ab", true, "ac", true, "bc", false] Explanation CombinationIterator itr = new CombinationIterator("abc", 2); itr.next(); // return "ab" itr.hasNext(); // return True itr.next(); // return "ac" itr.hasNext(); // return True itr.next(); // return "bc" itr.hasNext(); // return False Constraints: 1 <= combinationLength <= characters.length <= 15 All the characters of characters are unique. At most 104 calls will be made to next and hasNext. It's guaranteed that all calls of the function next are valid.
解法:
保存构造体:vector<string>
解法一:Backtracking(回溯算法)
- 状态:到当前位置为止,构成的组合path。
- 选择:从给定组合元素的第pos个开始(前面的元素,path已经选择过),到最后一个都可选择。
- 递归退出条件:path.size=combinationLength(要求的组合大小)
代码参考:
1 class CombinationIterator { 2 public: 3 vector<string> comb; 4 int itr; 5 void dfs(string characters, int combinationLength, int pos, string path) { 6 if(combinationLength == path.length()) { 7 comb.push_back(path); 8 return; 9 } 10 for(int i=pos; i<characters.size(); i++) { 11 dfs(characters, combinationLength, i+1, path+characters[i]); 12 } 13 } 14 CombinationIterator(string characters, int combinationLength) { 15 itr=0; 16 dfs(characters, combinationLength, 0, ""); 17 } 18 19 string next() { 20 return itr!=comb.size()?comb[itr++]:""; 21 } 22 23 bool hasNext() { 24 return itr!=comb.size(); 25 } 26 }; 27 28 /** 29 * Your CombinationIterator object will be instantiated and called as such: 30 * CombinationIterator* obj = new CombinationIterator(characters, combinationLength); 31 * string param_1 = obj->next(); 32 * bool param_2 = obj->hasNext(); 33 */
解法二:
保存构造体:set<string>(由题意,有顺序要求)
bit组合法:
每个元素代表一个bit位,选择表示1,不选表示0
那么,题意中要求选择长度combinationLength的元素构成组合,即:选择所有元素构成bit中含有2个1的组合。
再将这两个1对应的元素拿出来,拼成解,加入解list中。
Suppose Input string - "abc" and combinationLength =2 now mask = 8 which is nothing but 2 power length of of "abc" now Itarate from 1 to 8 Num bit_rep no_of_set_bit a b c hold_set 1 0 0 1 1 0 0 1 nothing <= because combinationLength != no_of_set_bit 2 0 1 0 1 0 1 0 same case like upper one 3 0 1 1 2 0 1 1 "bc" <= combinationLength ==no_of 4 1 0 0 1 1 0 0 nothing 5 1 0 1 2 1 0 1 "ac" 6 1 1 0 2 1 1 0 "ab" 7 1 1 1 3 1 1 1 nothing <= because combinationLength != no_of_set_bit return that set in lexi order ["ab","ac","bc"] Now We Done Our Main Work
代码参考:
1 class CombinationIterator { 2 public: 3 //vector<string> comb; 4 set<string> comb; 5 //int itr; 6 set <string> :: iterator itr; 7 /*void dfs(string characters, int combinationLength, int pos, string path) { 8 if(combinationLength == path.length()) { 9 comb.push_back(path); 10 return; 11 } 12 for(int i=pos; i<characters.size(); i++) { 13 dfs(characters, combinationLength, i+1, path+characters[i]); 14 } 15 }*/ 16 void creatcomb(string s, int len) { 17 int maxn = 1<<s.length(); 18 for(int cmb=1; cmb<maxn; cmb++) { 19 //count the num of 1: 20 if(__builtin_popcount(cmb)!=len) continue; 21 string newcomb; 22 //the bit 1 in cmb means the alphbet in s would be selected. 23 for(int i=cmb, idx=0; i>0; i>>=1, idx++) { 24 if(i&1) newcomb+=s[idx]; 25 } 26 comb.insert(newcomb); 27 } 28 return; 29 } 30 CombinationIterator(string characters, int combinationLength) { 31 //itr=0; 32 creatcomb(characters, combinationLength); 33 itr=comb.begin(); 34 //dfs(characters, combinationLength, 0, ""); 35 } 36 37 string next() { 38 return itr!=comb.end()?*itr++:""; 39 } 40 41 bool hasNext() { 42 return itr!=comb.end(); 43 } 44 }; 45 46 /** 47 * Your CombinationIterator object will be instantiated and called as such: 48 * CombinationIterator* obj = new CombinationIterator(characters, combinationLength); 49 * string param_1 = obj->next(); 50 * bool param_2 = obj->hasNext(); 51 */