活跃农民
- 积分
- 336
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2020-2-14
- 最后登录
- 1970-1-1
|
提供一个C++的解法。Input可以任意大小(比如stream),唯一要求是有足够内存来存output vector。- #include <algorithm> // std::sort
- #include <cmath> // std::nan
- #include <utility> // std::pair
- #include <vector> // std::vector
- // Return the values and indexes of the top-k smallest/largest elements.
- std::vector<std::pair<double, size_t> > FindTopK(
- const std::vector<double>& input, size_t k, bool is_largest, bool sorted) {
- // Corner case, return empty vector.
- if (k == 0) {
- return std::vector<std::pair<double, size_t> >();
- }
- std::vector<std::pair<double, size_t> > result;
- result.reserve(k);
- // N iterations (N = input.size()), each iteration is O(k).
- // Total complexity is O(kN). If k is constant, O(N).
- for (size_t i = 0; i < input.size(); i++) {
- double v1 = input[i];
- if (result.size() < k) {
- result.emplace_back(v1, i);
- } else if (is_largest) {
- // Find top-k largest
- size_t min_index = 0; // Local index
- double min_value = result[0].first;
- // Complexity of this loop is O(k)
- for (size_t j = 1; j < k; j++) {
- double v2 = result[j].first;
- if (v2 < min_value) {
- min_index = j;
- min_value = v2;
- }
- }
- // The new value is larger than the current smallest
- if (v1 > min_value) {
- result[min_index] = std::make_pair(v1, i);
- }
- } else {
- // Find top-k smallest
- size_t max_index = 0; // Local index
- double max_value = result[0].first;
- // Complexity of this loop is O(k)
- for (size_t j = 1; j < k; j++) {
- double v2 = result[j].first;
- if (v2 > max_value) {
- max_index = j;
- max_value = v2;
- }
- }
- // The new value is smaller than the current largest
- if (v1 < max_value) {
- result[max_index] = std::make_pair(v1, i);
- }
- }
- }
- if (sorted) {
- // Complexity of sorting is O(k log k).
- if (is_largest) {
- struct {
- bool operator()(const std::pair<double, size_t>& a,
- const std::pair<double, size_t>& b) const {
- return a.first > b.first; // Descending order
- }
- } comparator;
- std::sort(result.begin(), result.end(), comparator);
- } else {
- struct {
- bool operator()(const std::pair<double, size_t>& a,
- const std::pair<double, size_t>& b) const {
- return a.first < b.first; // Ascending order
- }
- } comparator;
- std::sort(result.begin(), result.end(), comparator);
- }
- }
- return result;
- }
- // Return the k-th smallest/largest element and its index.
- // Total complexity O(kN + k). If k is constant, O(N).
- std::pair<double, size_t> FindKthTop(std::vector<double>& input, size_t k,
- bool is_largest) {
- // Corner case, return something representing invalid.
- if (k == 0) {
- return std::make_pair(std::nan(""), static_cast<size_t>(-1));
- }
- // O(kN)
- std::vector<std::pair<double, size_t> > top_k =
- FindTopK(input, k, is_largest, false);
- // O(k)
- if (is_largest) {
- std::pair<double, size_t> max_pair = top_k[0];
- for (size_t i = 1; i < k; i++) {
- std::pair<double, size_t> p = top_k[i];
- if (p.first > max_pair.first) {
- max_pair = p;
- }
- }
- return max_pair;
- } else {
- std::pair<double, size_t> min_pair = top_k[0];
- for (size_t i = 1; i < k; i++) {
- std::pair<double, size_t> p = top_k[i];
- if (p.first < min_pair.first) {
- min_pair = p;
- }
- }
- return min_pair;
- }
- }
复制代码 |
|