繁体   English   中英

使用最大堆解决“查找数组中第 K 个最大数”问题的时间复杂度是多少?

[英]What is the time complexity of using max heap to solve "Find the K-th largest number in the array" problem?

“找到数组中第 K 个最大的数”问题:

inputs: [3,2,1,5,6,4], k = 2
outputs: 5

inputs: [3,2,3,1,2,4,5,5,6], k = 4
outputs: 4

我知道这个问题可以通过quick selectmin heap算法来解决。 但是,我在这里关注的是使用max heap 步骤如下:

1. Build max heap form the whole given array, inplace.
2. Iterate k times. In each iteration, Take and remove the heap top.
3. The last heap top taken at the k-th iteration is the result.

以下是cpp中的代码:

void swap(vector<int>& nums, int i, int j) {
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

void heapify_down(vector<int>& nums, int parent_idx, int end_idx) {
    int left_idx = parent_idx * 2 + 1, right_idx = left_idx + 1;
    while (left_idx <= end_idx) {
        int largeset_idx = parent_idx;
        if (nums[left_idx] > nums[largeset_idx]) largeset_idx = left_idx;
        if (right_idx <= end_idx && nums[right_idx] > nums[largeset_idx]) largeset_idx = right_idx;
        if (largeset_idx != parent_idx) {
            swap(nums, parent_idx, largeset_idx);
            parent_idx = largeset_idx;
            left_idx = parent_idx * 2 + 1;
            right_idx = left_idx + 1;
        }
        else {
            return ;
        }
    }
}

void build_heap(vector<int>& nums) {
    for (int i = nums.size() - 1; i >= 0; i--) heapify_down(nums, i, nums.size() - 1);
}

int findKthLargest(vector<int>& nums, int k) {
    build_heap(nums);
    int cnt = 0, res, cur_end = nums.size() - 1;
    while (cnt != k) {
        res = nums[0];
        cnt += 1;
        swap(nums, 0, cur_end);
        cur_end -= 1;
        heapify_down(nums, 0, cur_end);
    }

    return res;
}

这种方法的时间复杂度是多少? 我在第一步中使用自下而上的方法,这一步应该是 O(n)。 但是,while 循环让我感到困惑。 循环执行 k 次,每个循环都会调用heapify_down ,复杂度为 O(log(n))。 那么整体复杂度是O(n + k * log(n)) = O(max(n, k * log(n)))吗? 如我错了请纠正我。

如果你做对了,构建一个堆是O(n)并且移除顶部是O(log n)并且k未绑定它可能是n

所以总的来说它是O(n + k * log n) == O(n + n * log n) == O(n log n)

您没有更多信息,例如k < log n之类的吗?


构建堆时不要使用heapify_down ,因为这会导致 O(n * log n)。 相反,如果堆的大小为奇数,则首先忽略最后一个元素。 然后从i = size / 2 - 1开始并交换i2 * i2 * i + 1 ,因此最大的是i 重复直到i-- = 0 如果大小是奇数,则将最后一个元素添加到堆中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM