Algorithm 消除二进制矩阵中的重复项。它能比O(n^2)更及时地完成吗

Algorithm 消除二进制矩阵中的重复项。它能比O(n^2)更及时地完成吗,algorithm,Algorithm,输入 [0 1 0 0 1, 1 0 1 1 0, 0 1 0 0 1, 110] 预期产量 [0 1 0 0 1, 1 0 1 1 0, 110] 我能想出的解决办法是: 对于每一行,将其转换为十进制(或使用一些校验和方法),取O(n) 这实际上是将矩阵转换为一维数组 现在使用哈希表,扫描所有元素 跟踪重复项并仅报告此数组中的唯一元素 其他解决方案可能包括使用TRIE(或类似结构)。但这仍然需要O(n^2) 有更好的解决方案吗?为什么不将二进制值存储在整数中(就像存储位字段一样),然后使用快速

输入 [0 1 0 0 1, 1 0 1 1 0, 0 1 0 0 1, 110]

预期产量 [0 1 0 0 1, 1 0 1 1 0, 110]

我能想出的解决办法是:

  • 对于每一行,将其转换为十进制(或使用一些校验和方法),取O(n)
  • 这实际上是将矩阵转换为一维数组
  • 现在使用哈希表,扫描所有元素
  • 跟踪重复项并仅报告此数组中的唯一元素
  • 其他解决方案可能包括使用TRIE(或类似结构)。但这仍然需要O(n^2)


    有更好的解决方案吗?

    为什么不将二进制值存储在整数中(就像存储位字段一样),然后使用快速排序或合并排序对整数进行排序。然后遍历排序列表,检查重复项。重复值将始终直接相邻,因为它已排序。这需要O(n logn+n),其中n是矩阵中的行数。然而,每一个操作都会非常快,因为它是由一个整数的比较、交换和相等性检查组成的,在现代硬件上非常快。

    你可以在线性时间内通过计算每一行的散列,对散列进行Bucket排序(有史以来最快的整数排序),然后从排序的行中删除重复项(对于每一行,将当前行与上一行进行比较,如果匹配,则删除当前行)

    编辑:因为每个人都被否决了,显然有人不明白迭代N项是线性的,不管它们是如何排列的,我将详细说明

    Big-O计算不考虑集合在内存中的排列方式,除非存储机制不允许有效的恒定检索时间。数组,无论有多少个维度,都被认为是可以从中检索的有效常量。因此,我们应该考虑将整个5x5矩阵作为一个线性运算,因为它基本上与给定25个对象的一维数组相同。 这样一来:

    • 对所有元素进行散列(一次5个元素)是线性的,因为我们需要精确读取每个元素一次,才能将它们添加到该行的散列中(可以简单地将每个元素乘以10^x或2^x,然后添加到一个运行总数)

    • BucketSort算法在X*M时间内对最大数量级为M的X元素的一维数组执行。在这种情况下,X是整个操作的总N的平方根,最坏情况下的最大数量级M也将是N的平方根,我们的BucketSort将在O(X*M)~=O(N)内执行最坏的情况

    • 通过排序的散列进行迭代是线性的,顺序是总N的平方根


    因此,在N个值的矩阵上执行的这个算法的总复杂度大约是O(2N+sqrt(N)),这被认为是O(N)。

    矩阵中有
    N^2
    单元,您需要读取所有单元,因此任何可能的算法都至少是
    O(N^2)
    。好吧,这取决于
    n
    是什么。假设n是矩阵的维数(即nxn),你永远无法得到小于O(n^2),因为这是扫描整个过程所需的时间。@Ross,phkahler-你所称的n^2项实际上只是n。在计算大O时,行数和列数并不重要;元素的总数不存在。这很容易成为一个由N个元素组成的一维数组,一次从中获取元素X,你的大O符号不应该改变,但你的计数方式会改变。如果你将矩阵转换成整数数组,这可能很有趣。但是要将它们转换成整数,您需要遍历整行(O(n))*行数->O(n^2)。或者我错了吗?不,因为您最初将把值存储在一个类似于位字段的整数中。首先,您必须将数据存储在某个位置,因此为什么不使用易于处理的格式;)@伊利亚特-请看我对OP.N的评论。它应该被视为输入中元素的总数,而不仅仅是一个维度的基数。如果迭代一个包含25个元素的一维数组是线性的(根据定义,它是线性的),那么迭代一个包含25个元素的5x5矩阵也是线性的,因此执行时间大致相等。@KeithS很好,这个解决方案的时间是O(ceil(n/x)^ceil(n/x)*log(ceil(n/x)^ceil(n/x))+ceil(n/x))其中n是元素数量,x是系统上最大整数类型的位数。顺便说一句,我告诉他另一种存储元素的方法,这样算法一开始就可以在较小的n上运行。由于位字段的属性,算法将删除重复的整数而不是重复的行。@KeithS-绝对。我把n和n搞混了。是的,不可能有更快的解决方案,因为我们至少需要读取所有n(=n*n)元素。OP需要更快的解决方案,而不仅仅是较慢的解决方案。我不知道你为什么认为这是线性时间。。。这个解是O(n+n+k+n)最佳情形和O(n^2+n^2+n)最坏情形。不是O(n)@JustSid:为什么你认为解决方案比较慢?计算散列O(n),BucketSort O(n)(如果输入数组是正态分布的),删除重复的O(n)。给出O(3n)还是我错了?@JustSid-我看不出你怎么认为这慢了。我一步一步地研究了这个算法,最重要的一项是线性的,所以这个算法是线性的。