java 一个时间复杂度为O(m(logn + logm))的n*m矩阵排序算法

dsekswqp  于 2023-06-20  发布在  Java
关注(0)|答案(2)|浏览(90)

我最近遇到了一个面试问题。
我们有一个m*n矩阵,使得每行都是非降序的(用不同的元素排序)。设计一个O(m (log m+ log n))阶的算法来找到这个矩阵上的第k个最小元素(只有一个元素是第k个最小元素)。
我认为这是不可能的,所以在谷歌上搜索,找到this linkanother solution和这个类似问题的答案。
我认为如下:
1.将所有行的中位数放入一个数组中,我们在O(m)中找到这个数组的中位数,并将其称为pivot
1.我们在O(m log n)中找到这个元素的秩。即:在每一行中有多少元素低于在步骤(1)中找到的枢轴。
1.通过比较k和“主元的秩”,我们可以知道在每行中工作在右半部分或左半部分。(简化为m*n/2矩阵。)
但该算法的时间复杂度为O(m * log^2 n)。什么是可以在O(m (log n + log m))上工作的算法?有什么办法吗?

b09cbbtk

b09cbbtk1#

m行n列

  • 您是否必须要一个复杂度为O(m (log m+ log n))的解决方案?
  • 我可以想到一个复杂度为O(k * log-m)的解决方案,额外的空间为O(m)
  • 对于这种复杂性,可以使用修改后的PriorityQueue(heap)DataStructure
class PQObject {
    int value; // PQ sorting happens on this int..
    int m; // And m and n are positions.
    int n;
}
  • 您可以将第一列中的所有值放入优先级队列,然后开始弹出,直到第k个最小的元素
  • 每次弹出时,在弹出的对象中使用m和n重新插入该行的下一个值。
  • 最终问题归结为在M个排序数组中找到第k个最小元素。
bbmckpt7

bbmckpt72#

A recent paper by Kaplan et al给出了这个问题的最佳算法,至少从大O的Angular 来看是这样。具体来说,通过使用软堆数据结构,他们给出了在时间上运行的算法

  • 当k ≤ 2m时,时间复杂度为O(m + k);
  • 对于k ≥ 2m的情形,其时间复杂度为O(m log(k/m));和/或
  • 一般来说,时间复杂度为O(m + Σ log(ni +1)),其中ni是第i行中小于或等于第k个最小项的项数。

所有这些运行时都是最优的,因为假设我们只能使用基于比较的算法,没有一个运行时可以在大O意义上得到改进。
这里涉及的算法是平凡的,但比以前的算法满足类似的时间界限简单得多。软堆数据结构的使用是使一切正确和快速工作的关键。

相关问题