我使用最大堆来查找数组中的k个最大元素,如下所示:
1) 我已经构建了给定数组的前k个元素(arr[0]到arr[k-1])的最小堆MH。O(k)
2)对于每个元素,在第k个元素(arr[k]到arr[n-1])之后,将其与MH的根进行比较。
……a)如果元素大于根,则将其设为根,并为MH调用heapify
……b)否则忽略它。
//步骤2是O((n-k))
3)最后,MH有k个最大元素,MH的根是第k个最大元素。
我已经在网上搜索过了,第二步的复杂性显示了O(n-k)logk,我认为如果我们使用自底向上方法构建堆,它应该是(n-k)*O(k)。因为在每一步,只要找到一个更大的元素,我都会替换根。对k个元素的数组进行重分类的复杂度为O(k)
我错了吗?请澄清。我只是想知道我的想法是否正确?
我的方法如下:
private static void createMinHeap(int[] arr) {
for (int i = arr.length / 2; i >= 0; i--) {
restoreDown(arr, i);
}
}
private static void restoreDown(int[] arr, int i) {
int left = (2 * i) + 1;
int right = (2 * i) + 2;
int num = arr[i];
while (right <= arr.length) {
if (num <= arr[right] && num <= arr[left]) {
arr[i] = num;
return;
} else if (arr[right] < arr[left]) {
arr[i] = arr[right];
i = right;
} else {
arr[i] = arr[left];
i = left;
}
left = (2 * i) + 1;
right = (2 * i) + 2;
}
if (left == arr.length - 1 && arr[left] < num) {
arr[i] = arr[left];
i = left;
}
arr[i] = num;
}
选择算法允许您在O(n)时间内找到数组中的第k个元素或第k个最大元素。
您的推理几乎正确,但是对于大小为k的堆,heapify操作需要O(log k)。因此,总复杂度为O(n log k)。为什么?在最坏的情况下,您应该为剩余的每个元素执行heapify。由于k
是固定的,并且
n
可以任意大,即
O(n)
步长,最后得出O(n log k)
。
另请参见:
堆排序
所以我正在研究一个Leetcode问题,我的代码在某些情况下有效,但在某些情况下失败。 问题是: 给定一个矩阵,其中每个行和列都按升序排序,找出矩阵中第k个最小的元素。 请注意,它是排序顺序中的第k个最小元素,而不是第k个独立元素。 例子: 返回: 13 我的方法是使用minHeap,即使它声明数组已经排序,我仍然需要确保我已经将它从最小值排序到最大值。 这是我的代码: 以下是我的意见: 以下是输
我在一次采访中遇到了以下问题。 给定一个数组,您需要找到所有元素小于给定值 k 的子数组 ,例如 现在,值小于 4 的子数组是: 注意{4}是如何重复的,但没有考虑两次。现在,代码应该返回不同子阵列的计数 在本例中为3. 另一个示例: 不同的子阵列: 我的方法是找到小于给定值k(即O(n^2))的子阵列,然后将其插入类似无序集的内容中以删除重复项。 有没有解决这个问题的有效方法?
这是一个面试问题。 在具有排序行和列的矩阵中找到Kth最小元素。 Kth最小元素是中的一个,例如,这是否正确?
我实现了c程序,可以找到矩阵的元素:行的最大元素,同时列的最小元素,或行的-min元素,同时列的最大元素。例如,我们有数据。包含以下内容的txt文件: 4 7 8 9 10 6 5 4 11 5 0 1 12 4 2 7 13- 其中4是n-矩阵大小(4x4),7和10是这些数字。 下面是代码: 问题:我想知道我的代码是不是“脏”代码?因为我总是渴望让一切变得如此困难,只要有可能让它变得容易。是否
如果您有长度的排序数组,请查找其中最小的元素。这里有一些潜在的解决方案,有些涉及最小堆或二进制搜索,但我想知道使用QuickSelect的时间复杂度是多少。如果我们简单地将每个数组连接在一起,并在组合数组上使用quickselect。 Quickselect在一般情况下以线性时间运行,但是数组的组合确实会扩展搜索空间,但它比使用合并策略更有效,因为如果选择了好的枢轴,Quickselect必然允许