使用堆在 O(n + klogk) 中获取按排序顺序输出的数组中的最大 k 个元素?
Getting largest k elements in an array outputted in sorted order in O(n + klogk) using heaps?
我试图将算法的运行时间降低到 O(n + klogk),但我似乎做不到。我通过使用最小堆得到 O(n + nlogk)。基本上算法如下:
构建给定数组的前 k 个元素(arr[0] 到 arr[k-1])的最小堆 MH。 O(k)
对每个元素,在第k个元素(arr[k]到arr[n-1])之后,与MH的根进行比较。 O((n-k)logk)
最后,MH有k个最大的元素,MH的根是第k大的元素。调用 extractMin k 次得到 O(klogk)。
这让我得到 O(k + (n-k)Logk + kLogk),等于 O(k + nlogk)。但我需要 O(n + klogk)。
我不知道如何使用最小堆来加快速度。有什么建议么?
使用这种 min-heap 方法的问题是您必须不断地处理整个数组的其余部分,从而为您提供 [=11= 的 n
因子 in-front ].
有一种方法可以减少实际提取前k
个元素所做的工作,方法是使用divide-and-conquer 类似于快速排序的策略。这会以指数方式减少数组中必须处理的部分。
- Select 随机枢轴元素。
- 将数组分成比主元大和小的部分,就像在快速排序中一样。假设左边有
L
,右边有R
。
- 如果
k == L
那么我们就完成了:数组中的前 k
个元素是最小的。
- 如果
k < L
则从1继续,只处理左边的分区。
- 如果
k > L
则从 1 继续,使用新值 k' = k - L
处理正确的分区。
如果上面的描述含糊不清(编辑:可能是),这种方法是众所周知的,并且有很多来源(here's one 来自 SO,带有代码)。
假设平均情况下pivot将数组大致平分为两半(这也是理想情况),时间复杂度递归关系由T(m) = T(m/2) + O(m)
给出,也就是说上述算法是 O(n)
.
在此之后,数组的前 k
个元素是无序的,因此只需在 O(k log k)
处对它们进行排序。因此,根据需要,总复杂度为 O(n + k log k)
。
我试图将算法的运行时间降低到 O(n + klogk),但我似乎做不到。我通过使用最小堆得到 O(n + nlogk)。基本上算法如下:
构建给定数组的前 k 个元素(arr[0] 到 arr[k-1])的最小堆 MH。 O(k)
对每个元素,在第k个元素(arr[k]到arr[n-1])之后,与MH的根进行比较。 O((n-k)logk)
最后,MH有k个最大的元素,MH的根是第k大的元素。调用 extractMin k 次得到 O(klogk)。
这让我得到 O(k + (n-k)Logk + kLogk),等于 O(k + nlogk)。但我需要 O(n + klogk)。
我不知道如何使用最小堆来加快速度。有什么建议么?
使用这种 min-heap 方法的问题是您必须不断地处理整个数组的其余部分,从而为您提供 [=11= 的 n
因子 in-front ].
有一种方法可以减少实际提取前k
个元素所做的工作,方法是使用divide-and-conquer 类似于快速排序的策略。这会以指数方式减少数组中必须处理的部分。
- Select 随机枢轴元素。
- 将数组分成比主元大和小的部分,就像在快速排序中一样。假设左边有
L
,右边有R
。 - 如果
k == L
那么我们就完成了:数组中的前k
个元素是最小的。 - 如果
k < L
则从1继续,只处理左边的分区。 - 如果
k > L
则从 1 继续,使用新值k' = k - L
处理正确的分区。
如果上面的描述含糊不清(编辑:可能是),这种方法是众所周知的,并且有很多来源(here's one 来自 SO,带有代码)。
假设平均情况下pivot将数组大致平分为两半(这也是理想情况),时间复杂度递归关系由T(m) = T(m/2) + O(m)
给出,也就是说上述算法是 O(n)
.
在此之后,数组的前 k
个元素是无序的,因此只需在 O(k log k)
处对它们进行排序。因此,根据需要,总复杂度为 O(n + k log k)
。