Iterator for Combination (M)
题目
Design an Iterator class, which has:
- A constructor that takes a string
characters
of sorted distinct lowercase English letters and a numbercombinationLength
as arguments. - A function next() that returns the next combination of length
combinationLength
in lexicographical order. - A function hasNext() that returns
True
if and only if there exists a next combination.
Example:
CombinationIterator iterator = new CombinationIterator("abc", 2); // creates the iterator.
iterator.next(); // returns "ab"
iterator.hasNext(); // returns true
iterator.next(); // returns "ac"
iterator.hasNext(); // returns true
iterator.next(); // returns "bc"
iterator.hasNext(); // returns false
Constraints:
1 <= combinationLength <= characters.length <= 15
- There will be at most
10^4
function calls per test. - It's guaranteed that all calls of the function
next
are valid.
题意
给定一个字符串s和一个整数k,从s中选出k个字符组成排列,按顺序求出每一个排列。
思路
维护一个长度为k的数组selected,selected[i]表示当前排列中第i个字符在s中的下标。显然,为了使一个排列合法,selected[i]不能超过一个特定的值(s.length-(selected.length-i)),不然s中剩余的字符个数不足以填充到k。如果selected[i]小于这个特定值,则只要将selected[i]指向下一个字符,并重置i之后所有的位置为其第一个合法位置,即可得到下一个排列;如果selected[i]等于这个特定值,则缩小i重复操作。
代码实现
Java
class CombinationIterator {
private String s;
private int[] selected;
private boolean init;
public CombinationIterator(String characters, int combinationLength) {
s = characters;
selected = new int[combinationLength];
for (int i = 0; i < combinationLength; i++) {
selected[i] = i;
}
init = true;
}
public String next() {
if (init) {
init = false;
return generate();
}
for (int i = selected.length - 1; i >= 0; i--) {
int end = s.length() - (selected.length - i);
if (selected[i] < end) {
selected[i]++;
int j = 1;
while (i + j < selected.length) {
selected[i + j] = selected[i] + j;
j++;
}
break;
}
}
return generate();
}
public boolean hasNext() {
return s.length() - selected[0] > selected.length;
}
private String generate() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < selected.length; i++) {
sb.append(s.charAt(selected[i]));
}
return sb.toString();
}
}