我有一个字符串数组,值只有0和1。
示例:[“100”、“110”、“010”、“011”、“100”]
现在,我想将每个字符串与所有其他字符串进行比较,看看其中有多少字符串相差1。例如:
“100”与“110”相比,检查每个索引处的元素,如果它们最多相差1个位置,则认为它们相似。因此,对于上面数组中的字符串“100”,类似的元素是“110”和“100”。
我的程序返回一个整数数组,其中每个值表示列表中该索引处类似字符串的数量。
例子:
输入:
["100" , "110", "010", "011", "100"]
输出:[2,3,2,1,2]
说明:在索引1处,输入为“110”,类似的字符串为3,分别为“100”、“010”、“100”。
这是我的密码:
static List<Integer> process(String[] input) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < input.length; i++) {
int count = 0;
for (int j = 0; j < input.length; j++) {
if (i != j) {
int differ = 0;
for (int k = 0; k < input[i].length(); k++) {
if (input[i].charAt(k) != input[j].charAt(k)) {
differ++;
}
if (differ > 1) {
break;
}
}
if (differ <= 1) {
count++;
}
}
}
list.add(count);
}
return list;
}
如何提高此代码的时间复杂度?
所有字符串的长度相同,长度范围为1到20。输入数组的大小最多为10000。
5条答案
按热度按时间ncecgwcz1#
我们可以利用所有输入字符串长度相同的事实,在字符0和1上构建一个简单的二进制基数树,并将匹配字符串的计数存储在叶子中。
然后,您可以使用递归函数为每个输入字符串导航树,最多考虑一个发散点,即访问具有相反字符的子级。您可以对以这种方式到达的所有叶节点求和。
首先,我们构建树:
然后我们使用递归来计算匹配的字符串。注意,如果我们到达叶子和
diff
是0,也就是说,我们找到了原始字符串,然后我们需要将计数减少1,因为我们不计算自匹配。测试:
输出:
6xfqseft2#
你可以使用set。
把所有的字符串放在一起
s
对于每个字符串,生成因单个更改而不同的所有字符串计数属于的已生成字符串数
s
它将具有复杂性O(n*m*m)
而不是O(n*n*m)
你的算法已经成功了。n
是字符串和的数目m
是字符串的长度。因此,这是更好的方面
n
,但更糟糕的是m
.还需要
O(n*m)
记忆。原始算法需要O(max(log(n), log(m)))
记忆。为了获得更好的性能,请将字符串转换为整数。
inb24sb23#
我真的很喜欢拉弗尔的答案,它使用了根树。
但作为一种更快实现的替代方案,您可以使用
int[]
作为频率Map:索引i
存储数字的多少份副本i
在input
.频率Map数组的大小取决于输入字符串的宽度-因此它取决于
int[220] == int[1'048'576]
.hmae6n7t4#
弗兰肯斯坦的答案来自:
使用
Set
(实际上HashMap
支持重复输入数字),如talex的答案中所示使用
Integer.valueOf(String, 2)
将输入转换为int
史莱恩斯大师的答案中的数字使用位翻转计算闭合值,如用户16394029的答案所示
我们得到的代码是:
t40tm48m5#
我可以提出一个建议
O(N^2)
方法使用bitwise XOR
. 如果两位不同,则异或的结果为1。因此,我们可以使用这个属性来找到位不同的位置的计数。我用过
bitCount
方法java.lang package
它返回一个数的二元补码二进制表示中的一位数的计数,以查找结果中的设置位XOR
. 结果中的设置位数XOR
表示两个数字之间的许多位置不同。