题目

Design an Iterator class, which has:

  • A constructor that takes a string characters of sorted distinct lowercase English letters and a number combinationLength 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:

  1. CombinationIterator iterator = new CombinationIterator("abc", 2); // creates the iterator.
  2. iterator.next(); // returns "ab"
  3. iterator.hasNext(); // returns true
  4. iterator.next(); // returns "ac"
  5. iterator.hasNext(); // returns true
  6. iterator.next(); // returns "bc"
  7. 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

  1. class CombinationIterator {
  2. private String s;
  3. private int[] selected;
  4. private boolean init;
  5. public CombinationIterator(String characters, int combinationLength) {
  6. s = characters;
  7. selected = new int[combinationLength];
  8. for (int i = 0; i < combinationLength; i++) {
  9. selected[i] = i;
  10. }
  11. init = true;
  12. }
  13. public String next() {
  14. if (init) {
  15. init = false;
  16. return generate();
  17. }
  18. for (int i = selected.length - 1; i >= 0; i--) {
  19. int end = s.length() - (selected.length - i);
  20. if (selected[i] < end) {
  21. selected[i]++;
  22. int j = 1;
  23. while (i + j < selected.length) {
  24. selected[i + j] = selected[i] + j;
  25. j++;
  26. }
  27. break;
  28. }
  29. }
  30. return generate();
  31. }
  32. public boolean hasNext() {
  33. return s.length() - selected[0] > selected.length;
  34. }
  35. private String generate() {
  36. StringBuilder sb = new StringBuilder();
  37. for (int i = 0; i < selected.length; i++) {
  38. sb.append(s.charAt(selected[i]));
  39. }
  40. return sb.toString();
  41. }
  42. }