从矩阵中删除列后的唯一行

时间:2014-08-30 11:00:26

标签: algorithm language-agnostic

给出了n行和m列的二进制矩阵。 nm最多可达200​​0个。

我们需要告诉您,是否可以删除列,以便剩余矩阵的行将是唯一的。

n = 3m = 4的示例:

1010
0001
1001

答案是。我们可以删除第二列,其余行(110001101)将是唯一的。

n = 4m = 2的示例:

00
01
10
11

答案是。无论我们选择哪一列,行00都会保留。

I have O(m * m * n)暴力算法。我通过删除每一列来检查行的唯一性。

你知道更快的算法吗?

2 个答案:

答案 0 :(得分:1)

!编辑:我的解决方案不幸只有一半解决这个问题,抱歉。

我确信,我可以在O(m * n)时间内完成。

您可以在n * m时间内创建树。只需逐行排列并更新此结构:

Node{
 int accessed;
 Node nextZero;
 Node nextOne;
}

如果你确实创建了这棵树,你只需要检查最后一行,如果它有"零"和"些"等于或大于两个。


有一个直观的例子说明处理两个数字后的样子。

distinct rows

你只是一行一行,总是从根开始。

例如,当您开始处理第二行时,您将以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中的一些数字。

  1. 我们可以在O(n*m)中计算所有这些数字。
  2. 我们将获得长度为a的数组n
  3. 我们可以创建一个数组b,其位置b[i]将是i a中数字O(n)的次数>
  4. 如果某个b[i]>1i,则答案为否
  5. 不,我们会尝试逐一删除列,这会相应地更改数字。例如,如果我们删除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)
  6. 中完成

    编辑:

    整个解决方案的复杂性是O(n*m)

    因为数字很大,你可以使用字典将数组b表示为稀疏数组,对于数字,你可以使用一些数据库来表示大数字。整个解决方案应该比蛮力更快。