0和1的字符串组合

时间:2019-07-03 22:15:00

标签: java algorithm data-structures

在一次采访中有人问我这个问题:

  

给出由01?组成的字符串s。问号可以   是01。找到该字符串的所有可能组合。

我想出了下面的代码,但我想知道这是否是解决问题的最佳方法,并且我对时间复杂度感到困惑?

  public static void main(String[] args) {
    List<String> output = new ArrayList<>();
    addCombinations("0?1?", 0, output);
    System.out.println(output);
  }

  private static void addCombinations(String input, int index, List<String> output) {
    for (int i = index; i < input.length(); ++i) {
      if (input.charAt(i) == '?') {
        addCombinations(input.substring(0, i) + "0" + input.substring(i + 1), i + 1, output);
        addCombinations(input.substring(0, i) + "1" + input.substring(i + 1), i + 1, output);
        return;
      }
    }
    output.add(input);
  }

3 个答案:

答案 0 :(得分:0)

很难说什么是最好的。如果它可以正常工作,可以理解并且性能不差,那么可能就可以了。

这是我写的一个简单的书,它使用一些簿记来跟踪要填补的职位。

   public static void main(String[] args) {
      List<String> bitStrings = generate("0?1?0?11");
      bitStrings.forEach(System.out::println);
   }

   public static List<String> generate(String pattern) {
      List<String> output = new ArrayList<>();

      //Starting bit template
      String start = pattern.replaceAll("\\?", "0");

      //get the changeable positions.
      int[] pos = IntStream.range(0, pattern.length()).filter(
            i -> pattern.charAt(i) == '?').toArray();

      // Now simply iterate thru the 2^n possibilities where
      // n is the number of changeable positions.
      for (int i = 0; i < 1 << pos.length; i++) {
         StringBuilder sb = new StringBuilder(start);
         int p = i;
         for (int k = 0; k < pos.length; k++) {
            sb.setCharAt(pos[k], (char) ((p & 1) + '0'));
            p >>= 1;
         }
         output.add(sb.toString());
      }
      return output;
   }

答案 1 :(得分:-1)

这是一种不使用递归并且不使用字符串连接的实现。

private static List<String> addCombinations(String input) {
    char[] chars = input.toCharArray();
    List<Integer> wildcardIndex = new ArrayList<>();
    for (int i = 0; i < chars.length; i++) {
        if (chars[i] == '?') {
            wildcardIndex.add(i);
            chars[i] = '0';
        }
    }
    if (wildcardIndex.size() > 31)
        throw new IllegalArgumentException("Too many wildcards (max 31): " + wildcardIndex.size());
    // Collections.reverse(wildcardIndex);
    List<String> output = new ArrayList<>(1 << wildcardIndex.size());
    NEXT: for (;;) {
        output.add(new String(chars));
        for (int i : wildcardIndex) {
            if (chars[i] == '0') {
                chars[i] = '1';
                continue NEXT;
            }
            chars[i] = '0';
        }
        break;
    }
    return output;
}

测试1

List<String> output = addCombinations("0?1?");
System.out.println(output);
[0010, 0110, 0011, 0111]

测试2

System.out.println(addCombinations("???"));
[000, 100, 010, 110, 001, 101, 011, 111]

测试3(不带reverse()调用)

System.out.println(addCombinations("???"));
[000, 001, 010, 011, 100, 101, 110, 111]

答案 2 :(得分:-1)

如果给定字符串中问号的数量为m,则可能的组合数量为2 ^ m。 那为什么呢?

对于“?”答案是“ 0”,“ 1”

对于“ ??”答案是“ 00”,“ 01”,“ 1,0”,“ 11”(将0和1以及每个结果“?” =(“ 0”,“ 1”))

对于“ ???”答案是“ 000”,“ 001”,“ 010”,“ 011”,“ 100”,“ 101”,“ 110”,“ 111”(将0和1以及每个“ ??”的结果相加)

问号标记为1时,可能的组合数为2 = 2 ^ 1。
当问号标记为2时,可能的组合数为2 * 2 = 4 = 2 ^ 2。
当问题标记数为3时,可能的组合数为4 * 2 = 8 = 2 ^ 3。
当问号数为4时,可能的组合数为8 * 2 = 16 = 2 ^ 4。
当问号标记为5时,可能的组合数为16 * 2 = 32 = 2 ^ 5。
当问号标记为6时,可能的组合数为32 * 2 = 64 = 2 ^ 6。
当问题标记数为7时,可能的组合数为64 * 2 = 128 = 2 ^ 7。

所以当问号标记为m时,可能的组合数目为2 ^ m。

从二进制系统中我们知道,从0到(2 ^ m)-1的每个数字都给出二进制0和1的组合。

因此,当长度为1时,我们可以考虑0到(2 ^ 1)-1 = 1

0 0
1 1 

所以当长度为2时,我们可以考虑0到(2 ^ 2)-1 = 3

0 00
1 01
2 10
3 11

因此,当长度为3时,我们可以考虑0到(2 ^ 3)-1 = 7

0 000
1 001
2 010
3 011
4 100
5 101
6 110
7 111

类似地,对于长度m,我们可以考虑0到(2 ^ m)-1。

所以我们可以取0到(2 ^ m)-1的每个数字。

  

对于每个数字,我们将检查从0到m-1的每一位。
      如果第ith位为0,我们将在ith'?'中放入0。
      如果第ith位为1,我们将在ith'?'中放入1。

因此,我们将得到2 ^ m个不同的字符串。

相关问题