📌  相关文章
📜  在数组中查找第 k 个最大和最小元素 - C++ (1)

📅  最后修改于: 2023-12-03 15:37:43.136000             🧑  作者: Mango

在数组中查找第 k 个最大和最小元素 - C++

在处理数组相关问题时,查找数组中第 k 个最大或最小元素是一种常见的需求。本文介绍如何使用 C++ 实现这种问题。

方法一:排序

数组中第 k 个最大或最小元素可以通过排序来解决。排序后,第 k 个元素即为所需元素。时间复杂度为 O(nlogn)。

以下是 C++ 实现:

// 查找第 k 个最大元素
int findKthLargest(vector<int>& nums, int k) {
    sort(nums.begin(), nums.end());
    return nums[nums.size() - k];
}

// 查找第 k 个最小元素
int findKthSmallest(vector<int>& nums, int k) {
    sort(nums.begin(), nums.end());
    return nums[k - 1];
}
方法二:堆排序

使用堆来查找第 k 个最大或最小元素可以将时间复杂度优化到 O(nlogk)。

以下是 C++ 实现:

// 查找第 k 个最大元素
int findKthLargest(vector<int>& nums, int k) {
    priority_queue<int, vector<int>, greater<int>> minHeap; // 小根堆
    for (int num : nums) {
        minHeap.push(num);
        if (minHeap.size() > k) {
            minHeap.pop();
        }
    }
    return minHeap.top();
}

// 查找第 k 个最小元素
int findKthSmallest(vector<int>& nums, int k) {
    priority_queue<int> maxHeap; // 大根堆
    for (int num : nums) {
        maxHeap.push(num);
        if (maxHeap.size() > nums.size() - k + 1) {
            maxHeap.pop();
        }
    }
    return maxHeap.top();
}
方法三:快速选择

快速选择是基于快速排序算法的一种改进。在快速排序中,每次递归时需要同时对左右子数组递归。而在快速选择中,仅需要递归一边即可,这样可以将时间复杂度优化到 O(n)。

以下是 C++ 实现:

int quickSelect(vector<int>& nums, int l, int r, int k) {
    if (l == r) {
        return nums[l];
    }
    int pivotIndex = l + rand() % (r - l + 1);
    int pivot = nums[pivotIndex];
    int left = l, right = r;
    swap(nums[l], nums[pivotIndex]);
    while (left < right) {
        while (left < right && nums[right] >= pivot) {
            right--;
        }
        nums[left] = nums[right];
        while (left < right && nums[left] < pivot) {
            left++;
        }
        nums[right] = nums[left];
    }
    nums[left] = pivot;
    int lessCount = left - l + 1;
    if (lessCount == k) {
        return nums[left];
    } else if (lessCount > k) {
        return quickSelect(nums, l, left - 1, k);
    } else {
        return quickSelect(nums, left + 1, r, k - lessCount);
    }
}

// 查找第 k 个最大元素
int findKthLargest(vector<int>& nums, int k) {
    return quickSelect(nums, 0, nums.size() - 1, nums.size() - k + 1);
}

// 查找第 k 个最小元素
int findKthSmallest(vector<int>& nums, int k) {
    return quickSelect(nums, 0, nums.size() - 1, k);
}

总结:

  • 使用排序的时间复杂度为 O(nlogn);
  • 使用堆排序的时间复杂度为 O(nlogk);
  • 使用快速选择的时间复杂度为 O(n)。

因此,针对不同的数据规模和数据特征,选择不同的算法来解决问题。