给出了n
行和m
列的二进制矩阵。 n
和m
最多可达2000个。
我们需要告诉您,是否可以删除列,以便剩余矩阵的行将是唯一的。
n = 3
和m = 4
的示例:
1010
0001
1001
答案是是。我们可以删除第二列,其余行(110
,001
,101
)将是唯一的。
n = 4
和m = 2
的示例:
00
01
10
11
答案是否。无论我们选择哪一列,行0
和0
都会保留。
I have O(m * m * n)暴力算法。我通过删除每一列来检查行的唯一性。
你知道更快的算法吗?
答案 0 :(得分:1)
!编辑:我的解决方案不幸只有一半解决这个问题,抱歉。
我确信,我可以在O(m * n)时间内完成。
您可以在n * m时间内创建树。只需逐行排列并更新此结构:
Node{
int accessed;
Node nextZero;
Node nextOne;
}
如果你确实创建了这棵树,你只需要检查最后一行,如果它有"零"和"些"等于或大于两个。
有一个直观的例子说明处理两个数字后的样子。
你只是一行一行,总是从根开始。
例如,当您开始处理第二行时,您将以root身份开始。第二行中的数字是" 101"。你取第一个数字,它是" 1",所以你进入nextOne节点。然后你得到" 0",所以你进入nextZero。然后你得到" 1",它不存在,所以你创建它。
毕竟,你只对"访问"感兴趣。在最深度节点中的数字,如果它们都有"访问"等于1,有所不同,否则,它们不是。
伪代码
Node{
int accessed;
Node nextZero;
Node nextOne;
}
bool isDistinct(){
Node root = new Node();
Node next;
for (int i=0;i<arr.length;i++){
Node actual = root;
for (int j=0;j<arr[i].length;j++){
if (arr[i][j] == 0){
next = actual.nextZero;
if (next == null){
next = new Node();
acutal.nextZero = next;
}
} else {
next = actual.nextOne;
if (next == null){
next = new Node();
acutal.nextOne = next;
}
}
actual = next;
actual.accessed++;
if ((j == arr[i].length - 1) && (actual >= 2)){
return false;
}
}
}
return true;
}
对不起,这真的只是&#34;中途和#34;要做到这一点,我没有正确地读到我应该做什么。但有一些想法,也许你可以从树中删除一个节点并有效地重新平衡它......
答案 1 :(得分:1)
每一行代表基数10中的一些数字。
O(n*m)
中计算所有这些数字。 a
的数组n
。b
,其位置b[i]
将是i
O(n)
的次数>
b[i]>1
有i
,则答案为否k
列,我们需要创建数组c
,它与数组b
具有相同的含义但没有k
列。为此,我们会初始化c[i]=b[i]
i<2^k
以及b[i]=1
i>=2^k
,然后我们会更新c[i-2^k]++
。如果某个c[i]>1
获得i
,则答案为否,并继续下一列。否则答案是肯定的。这可以在O(n*m)
。编辑:
整个解决方案的复杂性是O(n*m)
。
因为数字很大,你可以使用字典将数组b
表示为稀疏数组,对于数字,你可以使用一些数据库来表示大数字。整个解决方案应该比蛮力更快。