是否有比 O(N²) 更好的算法来确定矩阵是否对称?

Posted

技术标签:

【中文标题】是否有比 O(N²) 更好的算法来确定矩阵是否对称?【英文标题】:Is there an algorithm better than O(N²) to determine if matrix is symmetric? 【发布时间】:2013-12-02 22:19:14 【问题描述】:

算法要求

输入是大小为N×N 的任意方阵M正好 适合内存。

算法的输出必须是true,如果是M[i,j] = M[j,i],对于所有j≠i,否则false

明显的解决方案

    检查转置是否等于矩阵本身 (MT=M)。在许多环境中最容易编程,但(通常)消耗两倍的内存并且需要 比较最坏的情况。因此,这是 O() 并且具有高峰值内存。

    检查下三角部分是否等于上三角部分。当然,算法返回找到的第一个不等式。这将使最坏的情况(最坏的情况是,矩阵确实是对称的)需要N²/2 - N 比较,因为不需要检查对角线。所以虽然比选项1好,但这仍然是O()。

问题

虽然很难看出它是怎么可能的( 元素都必须以某种方式进行比较),但有没有比 O() 更好的算法来做这个检查?

或者,如果有证据证明不存在这种算法:如何在考虑到缓存友好性、最佳分支预测等因素的情况下最有效地为多核 CPU(Intel 或 AMD)实现这一点编译器特定的特化等?

这个问题主要源于学术兴趣,尽管我认为实际用途可能是确定如果矩阵描述线性系统AX=b...

【问题讨论】:

你能有一个稀疏矩阵表示吗? @Leeor: 是的,full 或 sparse 都应该支持 我只是说,对于稀疏图,如果元素的数量明显低于 n^2,您可能会获得更好的复杂性 对不起,因为我要说的可能很愚蠢。但是这里的 O(N^2) 让我感到困惑。如果您有一个大小为 S 的矩阵 M,其中 s=nxn,并且您的算法正在执行 S 次比较,那不是 O(n) 吗? @Pedrom 这将是 O(S),而不是 O(n),并且 O(S) 是 O(n^2)。 【参考方案1】:

由于您必须检查除对角线之外的所有元素,因此 IMO 的复杂度不能优于 O (n^2)。

【讨论】:

我也是这么想的,但这也是我第一次考虑排序时的想法:)我希望可以使用一些类似的“聪明的技巧”...... @RodyOldenhuis 对于矩阵 O(n^2) 等价于 no。元素,因为有 N^2 个元素。我看不出你怎么能做得比这更好。 我知道,但如果我对算法有什么了解的话,那就是“我看不出如何......”不是支持“它不存在”的论据。 @RodyOldenhuis 要获得正确的输出,您必须知道每个输入的某些属性,因为您没有给出输入矩阵的属性,因此您至少必须检查矩阵的所有元素。有些人争辩说,当他们说二进制搜索是 O(logn) 时,它小于读取每个值一次,但是考虑到数组是排序的,有一个重要的属性告诉我们每个元素的数字比它前面的数字小,比它的数字大在它之后。这对于二分搜索的每个元素来说已经足够了。 复杂度不能小于 N^2,因为必须读取 N^2 - N 个值。证明结束。排序没有帮助。有 N^2 个元素,因此使用比较排序对它们进行排序将按顺序 (N^2*log(N^2) = O(N^2*logN) 已经大于 order(N^2)。 【参考方案2】:

对于密集矩阵,答案是肯定的“否”,因为任何未经检查的(非对角线)元素都可能与其转置的对应元素不同。

对于稀疏矩阵的标准表示,同样的推理表明您通常不能比输入大小做得更好。

但是,同样的推理不适用于任意矩阵表示。例如,您可以存储矩阵的对称和反对称分量的稀疏表示,通过检查反对称元素是否有任何分量,可以在 O(1) 时间内轻松检查对称性...

【讨论】:

【参考方案3】:

我认为您可以在这里采用概率方法。

我认为x 随机选择的较低坐标元素将与其上三角对应部分匹配并不是偶然/巧合。矩阵确实对称的可能性非常高

因此,您可以检查 p 随机坐标并确定矩阵是否对称,而不是遍历所有 ½n² - n 元素:

p / (½n² - n)

然后您可以确定一个阈值,超过该阈值您相信矩阵必须是对称矩阵。

【讨论】:

有趣的想法,这在许多情况下肯定就足够了。当然,不是全部:) 当需要绝对确定性(“最坏情况”)时,它仍然必须是 O(N²) 是的。我尝试编写乳胶样式,但它不支持预览。感谢您的编辑:)

以上是关于是否有比 O(N²) 更好的算法来确定矩阵是否对称?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以只保存对称矩阵的一半来节省内存?

回溯算法的复杂度

是否有比删除其目录更快/更好的方法来清除 iPhone 模拟器缓存?

九大排序算法时间复杂度空间复杂度稳定性

如何手动确定矩阵是不是对称?

只会用 Go 写 O(N²) 的冒泡排序算法?来看看优化后最好情况下的 O(N) 算法吧