简体   繁体   English

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

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

"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

I know that this problem can be soleved with quick select and min heap algorithms.我知道这个问题可以通过quick selectmin heap算法来解决。 However, what I'm focusing here is using max heap .但是,我在这里关注的是使用max heap The steps is the following:步骤如下:

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.

Below is the code in cpp:以下是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;
}

What is the time complextity of this method?这种方法的时间复杂度是多少? I'm using bottom-up approach in the first step, this step should be O(n).我在第一步中使用自下而上的方法,这一步应该是 O(n)。 However, the while loop makes me confused.但是,while 循环让我感到困惑。 The loop execute k times, each loop will call heapify_down which is O(log(n)) comlexity.循环执行 k 次,每个循环都会调用heapify_down ,复杂度为 O(log(n))。 So is the overall complexity O(n + k * log(n)) = O(max(n, k * log(n))) ?那么整体复杂度是O(n + k * log(n)) = O(max(n, k * log(n)))吗? Correct me if I'm wrong.如我错了请纠正我。

Building a heap, if you do it right, is O(n) and removing the top is O(log n) and with k being unbound it could be n .如果你做对了,构建一个堆是O(n)并且移除顶部是O(log n)并且k未绑定它可能是n

So overall it is O(n + k * log n) == O(n + n * log n) == O(n log n) .所以总的来说它是O(n + k * log n) == O(n + n * log n) == O(n log n)

Don't you have some more information, like k < log n or something?您没有更多信息,例如k < log n之类的吗?


When building your heap don't use heapify_down , because that results in O(n * log n).构建堆时不要使用heapify_down ,因为这会导致 O(n * log n)。 Instead first ignore the last element if the heap has odd size.相反,如果堆的大小为奇数,则首先忽略最后一个元素。 Then start at i = size / 2 - 1 and swap i , 2 * i and 2 * i + 1 around so the largest is at i .然后从i = size / 2 - 1开始并交换i2 * i2 * i + 1 ,因此最大的是i Repeat till i-- = 0 .重复直到i-- = 0 If the size was odd add the last element to the heap.如果大小是奇数,则将最后一个元素添加到堆中。

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

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