从1& 0,' s和?' s(问号)的字符串生成唯一字符串

时间:2013-11-01 03:14:15

标签: c++ algorithm big-o permutation time-complexity

最近,我被要求设计一个函数,它将包含一个包含1,0和?的任何一个字符串(例如:“10?10?1”,“00 ??? 11”,“? “等等)作为输入,并返回包含输入字符串的所有唯一的一零排列的字符串列表。

对于“10?1?”的输入,答案将是包含“10010”,“10110”,“10011”和“10111”的列表。

我能够设计出一个能够做到这一点的功能,但它本质上是一种蛮力,我对一个复杂性为O(2 ^ n)的更清晰的功能感兴趣。非常感谢提供算法和/或实现,谢谢!

7 个答案:

答案 0 :(得分:2)

我认为你不能比“强力”实施做得更好。对于提供包含N个问号的任何此类字符串,将存在2 ^ N个唯一排列。实际上,您所能做的就是以您喜欢的顺序尝试所有不同的字符串。至于算法:

  • 获取指向字符串中存在问号并存储在数组中的所有位置的指针。
  • 获取一个比问号数长的无符号整数变量(使用long long来保证安全);设为0.
  • 变量中的位代表问号的所有可能组合。因此,使用按位运算将1和0替换为问号,并且每次将变量增加1.
  • 重复2 ^ N次。

答案 1 :(得分:2)

您可以将其视为每个节点都有点的树。每个问号产生2个节点:0和1.任何不是问号的东西都只是具有相同值的节点。例如,对于10?1?的输入,树将像这样展开:

enter image description here

这是一个C实现:

void generate_str(char *str, int pos) {
    if (str[pos] == '\0') {
        printf("%s\n", str);
        return;
    }
    if (str[pos] == '?') {
        str[pos] = '0';
        generate_str(str, pos+1);
        str[pos] = '1';
        generate_str(str, pos+1);
        str[pos] = '?'; /* We can get back to this branch because of an earlier '?' */
    }
    else {
        generate_str(str, pos+1);
    }
}

请注意,您必须将位置设置回“?”在探索该分支之后,因为您可能来自另一个分支,之后您将需要识别与再次出现问号相同的位置。

您可以像这样调用此函数:

int main(void) {
    char test[] = "10?1?";
    generate_str(test, 0);
    return 0;
}

你不能比O(2^n)做得更好,因为你必须至少打印输出。

答案 2 :(得分:1)

它会控制这样的字符串

 arr = "4646555?45656?564465?";
    function A(arr){var k = arr.indexOf("?");
    if(k != -1){
        R = arr.slice(0,k);
        L = arr.slice(k+1,arr.length);
        let M = R +"0"+ L;
        let N = R +"1"+ L;


        if(M.indexOf("?") != -1) A(M);
        else console.log(M)
        if(N.indexOf("?") != -1) A(N);
        else console.log(N)
    }
    }
    A(arr)

答案 3 :(得分:1)

我有一个递归解决方案

input_str = "10??01"

# 100001
# 100101
# 101001
# 101101

def solution(res, a, n):
  if n == 1 and a[0] != "?":
    print(res+a[0])
    return

  elif n == 1 and a[0] == "?":
    print(res+"0")
    print(res+"1")
    return


  if a[0] != "?":
    solution(res+a[0], a[1: ], len(a[1: ]))

  elif a[0] == "?":
    solution(res+"0", a[1: ], len(a[1: ]))
    solution(res+"1", a[1: ], len(a[1: ]))


solution("", input_str, len(input_str))

答案 4 :(得分:0)

总体思路:

  • 创建一个带string或字符数组和位置的函数。

  • 从位置0开始。

  • 增加位置,直到我们在?的位置找到string

  • 如果我们在字符串的末尾,则输出并返回。

  • 否则将该位置的字符设置为1并从下一个位置递归,然后递归0并递归。

复杂性:O(size of string + 2^(number of question marks))

答案 5 :(得分:0)

with open ('report.csv', 'wb') as file:
    writer = csv.writer(file)
    writer.writerow(['UserName', 'arn', 'password-last-used'])
    for i in users:
       writer.writerow(
         [i.user_name, i.arn, i.get("password_last_used", 'Never Used')])

答案 6 :(得分:0)

用Java编写,但很容易转换为c ++。

基础是将问号?分隔为单个值。 然后在组合列表中放置一个值(0而不是所有?)。 然后迭代烤箱并在组合列表上,每次使用bitwise or分隔的问号?乘以它所保持的值的数量。

我们正在进行乘法d次,其中d是问号的数量。因此,我们大约运行2 ^ d时间,因此O(2 ^ d)。如果n是输入大小,则小于O(2 ^ n)。

空间复杂度是返回的数组 - O(n * 2 ^ d)。 2 ^ d字符串。每个字符串的大小为输入 - n。

*如果输入大于64位,我就省略了合并的计算。

public class BinaryCombinationsForQuestionMark {

    public static void main(String[] args) {
        System.out.println(Arrays.toString(getAllCombinations("1??")));
    }

    // TODO: If larger than 64 bit, separate to 64 and merge to original sizes
    public static int[] getAllCombinations(String input) {
        // TODO: Validate input
        // Doing up to 64 bits
        int numWithZerosAsQuestions = convertToNumWithQuestionsAsZeros(input);
        int[] separated = separateToOnesAsQuestions(input);

        List<Integer> combinations = new ArrayList<>();
        combinations.add(numWithZerosAsQuestions);
        for (int separate : separated) {
            // Prevents ConcurrentModificationException
            int size = combinations.size();
            for (int i = 0; i < size; i++) {
                int combination = combinations.get(i);
                combinations.add(combination | separate);
            }
        }
        return combinations.stream().mapToInt(i -> i).toArray();
    }

    private static int[] separateToOnesAsQuestions(String input) {
        ArrayList<Integer> separated = new ArrayList<>();
        for (int i = input.length() - 1; i >= 0; --i) {
            char c = input.charAt(i);
            if (c == '?') {
                separated.add(1 << input.length() - 1 - i);
            }
        }
        return separated.stream().mapToInt(i -> i).toArray();
    }

    private static int convertToNumWithQuestionsAsZeros(String input) {
        int num = 0;
        for (int i = 0; i < input.length(); ++i) {
            num <<= 1;
            char c = input.charAt(i);
            if (c == '1') num |= 1;
        }
        return num;
    }
}

干杯。