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中。

 

参考:LeetCode Thought

解法关联

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  */

 

posted @ 2021-01-30 18:03  habibah_chang  阅读(75)  评论(0编辑  收藏  举报