📌  相关文章
📜  使用 STL 的第 K 个最小最大元素(1)

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

使用 STL 的第 K 个最小/最大元素

在编写 C++ 代码时,我们有时需要从一个集合中查找第 K 个最小或最大的元素。STL 中提供了几个算法来解决这个问题。本文将介绍 STL 中的三种解决方案:std::nth_element、std::partial_sort 和 std::priority_queue。

std::nth_element

std::nth_element 是 STL 中用于排序的一个函数,它用来将一个区间内的元素进行部分排序,使第 K 个位置上的元素处于正确的位置,而其他未排序的元素则处于不确定的位置。这个函数的时间复杂度为 O(n),比较适合查找第 K 个最小元素。

下面是 std::nth_element 的使用示例:

#include <algorithm>
#include <vector>

int findKthSmallest(std::vector<int>& nums, int k) {
    std::nth_element(nums.begin(), nums.begin() + k - 1, nums.end());
    return nums[k - 1];
}

这个函数将 nums 中前 k 个元素部分排序,使第 k 个位置上的元素处于正确的位置。我们随后可以直接返回 nums[k - 1]。

注意,如果我们需要查找第 K 个最大元素,需要把 nums 中的元素按照从大到小的顺序排列。可以使用一个仿函数 (functor),传给 std::nth_element 来实现这个目标:

#include <algorithm>
#include <vector>

struct greater {
    template<class T>
    bool operator()(T const &a, T const &b) const { return a > b; }
};

int findKthLargest(std::vector<int>& nums, int k) {
    std::nth_element(nums.begin(), nums.begin() + k - 1, nums.end(), greater());
    return nums[k - 1];
}
std::partial_sort

std::partial_sort 是 STL 中另一个用于排序的函数,用来将一个区间内的元素进行部分排序,排序后前 K 个元素是这个区间内最小的 K 个元素。这个函数的时间复杂度为 O(nlogk),比较适合查找第 K 个最小元素。

下面是 std::partial_sort 的使用示例:

#include <algorithm>
#include <vector>

int findKthSmallest(std::vector<int>& nums, int k) {
    std::partial_sort(nums.begin(), nums.begin() + k, nums.end());
    return nums[k - 1];
}

这个函数将 nums 中前 k 个元素排序,使它们是最小的 k 个元素。我们随后可以直接返回 nums[k - 1]。

注意,如果我们需要查找第 K 个最大元素,需要把 nums 中的元素按照从大到小的顺序排列。可以使用一个仿函数 (functor),传给 std::partial_sort 来实现这个目标:

#include <algorithm>
#include <vector>

struct greater {
    template<class T>
    bool operator()(T const &a, T const &b) const { return a > b; }
};

int findKthLargest(std::vector<int>& nums, int k) {
    std::partial_sort(nums.begin(), nums.begin() + k, nums.end(), greater());
    return nums[k - 1];
}
std::priority_queue

std::priority_queue 是 STL 中用于优先队列的一个容器适配器,是一个元素的排列,每个元素都有一个权重。权重最小的元素总是被放在队列的最前面,而权重最大的元素总是被放在队列的最后面。这个容器适配器可以用来查找最小的 k 个元素,也可以用来查找最大的 k 个元素。

下面是 std::priority_queue 查找前 k 个最小元素的使用示例:

#include <queue>
#include <vector>

int findKthSmallest(std::vector<int>& nums, int k) {
    std::priority_queue<int> pq;
    for (int n : nums) {
        pq.push(n);
        if (pq.size() > k) pq.pop();
    }
    return pq.top();
}

这个函数创建了一个优先队列,用来存储 nums 中的元素。每当队列中的元素个数超过 k,我们就弹出队列中最大的元素。当遍历完 nums 的所有元素后,队列中剩下的 k 个元素就是 nums 中最小的 k 个元素。

注意,如果我们需要查找最大的 k 个元素,需要使用一个自定义的比较器。当我们把 nums 中的元素插入队列时,先取相反数,然后再插入队列中。这样权重最大的元素将被放在队列的最前面,权重最小的元素将被放在队列的最后面。

#include <queue>
#include <vector>

struct greater {
    bool operator()(const int& a, const int& b) const {
        return a > b;
    }
};

int findKthLargest(std::vector<int>& nums, int k) {
    std::priority_queue<int, std::vector<int>, greater> pq;
    for (int n : nums) {
        pq.push(n);
        if (pq.size() > k) pq.pop();
    }
    return pq.top();
}

以上就是使用 STL 查找第 K 个最小/最大元素的几种方法。如果需要查找第 K 个最小/最大元素,建议使用 std::nth_elementstd::partial_sort。如果需要查找最小的 k 个元素或最大的 k 个元素,建议使用 std::priority_queue