难度 medium
请你设计一个迭代器类,包括以下内容:
一个构造函数,输入参数包括:一个 有序且字符唯一 的字符串 characters(该字符串只包含小写英文字母)和一个数字 combinationLength 。
函数 next() ,按 字典序 返回长度为 combinationLength 的下一个字母组合。
函数 hasNext() ,只有存在长度为 combinationLength 的下一个字母组合时,才返回 True;否则,返回 False。
示例:
CombinationIterator iterator = new CombinationIterator("abc", 2); // 创建迭代器 iterator
iterator.next(); // 返回 "ab"
iterator.hasNext(); // 返回 true
iterator.next(); // 返回 "ac"
iterator.hasNext(); // 返回 true
iterator.next(); // 返回 "bc"
iterator.hasNext(); // 返回 false
提示:
1 <= combinationLength <= characters.length <= 15
每组测试数据最多包含 10^4 次函数调用。
题目保证每次调用函数 next 时都存在下一个字母组合。
解题思路:我们可以看到按照字典序排序编码如下,长度为2,比如:
abcd
则字典序排序应该是:
ab
ac
ad
bc
bd
刚好可以对应二进制数,从大到小:
1100
1010
1001
0110
0101
0011
观察到以上规律,我们就可以避免求出所有的全排列组合,依次按照二进制编码从大到小的顺序,将所有的字符串依次求出即可。
代码 t72 s90 java
class CombinationIterator {
public CombinationIterator(String characters, int combinationLength) {
int sz = characters.length();
this.cur = (1<<sz) - 1;
this.size = combinationLength;
this.key = characters;
}
public int countOne(int n){
int count = 0, i = 0;
while(n>0){
if((n & 1)==1) count++;
n = n>>1;
}
return count;
}
public String next() {
while(cur>0 && countOne(cur)!=size) cur--;
StringBuilder sb = new StringBuilder();
for(int i=key.length()-1; i>=0; i--){
if((cur & (1<<i))>>i==1){
sb.append(key.charAt(key.length()-1-i));
}
}
cur--;
return sb.toString();
}
public boolean hasNext() {
while(cur>0 && countOne(cur)!=size) cur--;
if(cur>0) return true;
return false;
}
private int cur;
private int size;
private String key;
}
代码 cpp
class CombinationIterator {
public:
CombinationIterator(string characters, int combinationLength) {
reverse(characters.begin(),characters.end());
this->key = characters;
this->curr = (1<<key.size())-1;
this->sz = combinationLength;
}
int countOne(int n){
int count = 0;
while (n != 0){
count++;
n = (n-1) & n;
}
return count;
}
string next() {
while(curr >= 0 && countOne(curr) != sz){
curr--;
}
string res;
for(int i = 0; i < key.size(); ++i){
if((curr&(1<<i))>>i){
res = key[i] + res;
}
}
curr--;
return res;
}
bool hasNext() {
while(curr >= 0 && countOne(curr) != sz){curr--;}
if(curr < 0){
return false;
}
return true;
}
private:
int curr;
int sz;
int maxCnt;
string key;
};
原文:https://www.cnblogs.com/zhengxch/p/14673220.html