最近,我被要求设计一个函数,它将包含一个包含1,0和?的任何一个字符串(例如:“10?10?1”,“00 ??? 11”,“? “等等)作为输入,并返回包含输入字符串的所有唯一的一零排列的字符串列表。
对于“10?1?”的输入,答案将是包含“10010”,“10110”,“10011”和“10111”的列表。
我能够设计出一个能够做到这一点的功能,但它本质上是一种蛮力,我对一个复杂性为O(2 ^ n)的更清晰的功能感兴趣。非常感谢提供算法和/或实现,谢谢!
答案 0 :(得分:2)
我认为你不能比“强力”实施做得更好。对于提供包含N个问号的任何此类字符串,将存在2 ^ N个唯一排列。实际上,您所能做的就是以您喜欢的顺序尝试所有不同的字符串。至于算法:
答案 1 :(得分:2)
您可以将其视为每个节点都有点的树。每个问号产生2个节点:0和1.任何不是问号的东西都只是具有相同值的节点。例如,对于10?1?
的输入,树将像这样展开:
这是一个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;
}
}
干杯。