美文网首页
TopK问题的思考

TopK问题的思考

作者: minhelloworld | 来源:发表于2020-03-30 20:47 被阅读0次

1、问题

什么是 Top K 问题?简单来说就是在一堆数据里面找到前 K 大(当然也可以是前 K 小)的数。这是一个非常经典的算法问题,不论是面试中还是实际开发中,都非常典型。

2、解决方案

2.1、直接排序

#include <iostream>
#include <vector>

std::vector<int> GetLeastNumbers(std::vector<int> input, int k) {
  std::vector<int> ans;
  if (k > input.size() || input.size() == 0 || k == 0) {
    return ans;
  }
  std::sort(input.begin(), input.end());
  for (int i = 0; i < k; i++) {
    ans.push_back(input[i]);
  }
  return ans;
}
int main() {
  std::vector<int> arr = {61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62};
  std::vector<int> ans = GetLeastNumbers(arr, 3);
  for (int i = 0; i < ans.size(); i++)
    std::cout << ans[i] << ' ';
  std::cout << std::endl;
  return 0;
}

时间复杂度: O(n*log(n))

2.2、局部排序

#include <iostream>
#include <vector>

std::vector<int> GetLeastNumbers(std::vector<int> input, int k) {
  if (k > input.size() || input.size() == 0 || k == 0) {
    return input;
  }

  for (int i = 0; i < k; i++) {
    for (int j = 0; j < input.size() - 1 - i; j++) {
      if (input[j] > input[j + 1])
        std::swap(input[j], input[j + 1]);
    }
  }

  std::vector<int>::const_iterator start = input.end() - k;
  std::vector<int>::const_iterator end = input.end();
  std::vector<int> anc(start, end);
  return anc;
}
int main() {
  std::vector<int> arr = {61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62};
  std::vector<int> ans = GetLeastNumbers(arr, 3);
  for (int i = 0; i < ans.size(); i++)
    std::cout << ans[i] << ' ';
  std::cout << std::endl;
  return 0;
}

时间复杂度: O(n*k)

分析:冒泡,将全局排序优化为了局部排序,非TopK的元素是不需要排序的,节省了计算资源。

2.3、堆排序

#include <iostream>
#include <vector>

using namespace std;

void BuildMaxHeap(vector<int> &input, vector<int> &heap, int k) {
  for (int i = 0; i < k; i++) {
    heap.push_back(input[i]);
  }
  sort(heap.begin(), heap.end());
  reverse(heap.begin(), heap.end());
}

void ShiftMaxDown(vector<int> &heap) {
  int cur_root = 0;
  int cur_left = 2 * cur_root + 1;
  int cur_right = 2 * cur_root + 2;
  while (true) {
    if (cur_left < heap.size() && heap[cur_root] < heap[cur_left]) {
      int temp = heap[cur_root];
      heap[cur_root] = heap[cur_left];
      heap[cur_left] = temp;
      cur_root = cur_left;
      cur_left = 2 * cur_root + 1;
      cur_right = 2 * cur_root + 2;
    } else if (cur_right < heap.size() && heap[cur_root] < heap[cur_right]) {
      int temp = heap[cur_root];
      heap[cur_root] = heap[cur_right];
      heap[cur_right] = temp;
      cur_root = cur_right;
      cur_left = 2 * cur_root + 1;
      cur_right = 2 * cur_root + 2;
    } else {
      break;
    }
  }
}

vector<int> GetLeastNumbers(vector<int> input, int k) {
  vector<int> ans;
  if (k > input.size() || input.size() == 0 || k == 0) {
    return ans;
  }
  BuildMaxHeap(input, ans, k);
  for (int i = k; i < input.size(); i++) {
    if (ans[0] > input[i]) {
      ans[0] = input[i];
      ShiftMaxDown(ans);
    }
  }
  return ans;
}

int main() {
  std::vector<int> arr = {61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62};
  std::vector<int> ans = GetLeastNumbers(arr, 3);
  for (int i = 0; i < ans.size(); i++)
    std::cout << ans[i] << ' ';
  std::cout << std::endl;
  return 0;
}

时间复杂度: O(n*log(k))

分析:不一定要用堆排序来处理这个,其他排序算法也可以做到这个时间复杂度~

相关文章

  • TopK问题的思考

    1、问题 什么是 Top K 问题?简单来说就是在一堆数据里面找到前 K 大(当然也可以是前 K 小)的数。这是一...

  • 海量数据处理

    topk问题

  • TOPK 问题

    TOPK 问题 描述 如从海量数字中寻找最大的 k 个,这类问题我们称为 TOPK 问题,通常使用堆来解决: 求前...

  • TopK 问题

    TopK分为两种:离线处理和实时流处理 非频率的 TopK 问题直接采用 PriorityQueue 就可以解决 ...

  • TopK问题

    出现次数最多的K个 解题步骤: 把所有的数据存到map里 构造K个的大根堆 输出大根堆 第K大的数 解题步骤: 方...

  • TopK问题

    从文件中输出请求最频繁的10个 HTTP 接口,及其相应的请求数量数据格式如下 从大数据中找到TopK个数,比较经...

  • topK问题

    连接:https://leetcode-cn.com/problems/top-k-frequent-elemen...

  • topk 问题

    排序后取前 K 个 算法复杂度 O(nlogn) 遍历 K 遍 算法复杂度 O(kn) k 跟元素的小/大根堆 算...

  • topK问题

    (1)时间复杂度分析:每次调用'self.heapAdjust(self.arr, n, i)'的时间复杂度是O(...

  • TopK

    问题描述: 从arr[1, n]这n个数中,找出最大的k个数,这就是经典的TopK问题。 什么是TopK,就是找到...

网友评论

      本文标题:TopK问题的思考

      本文链接:https://www.haomeiwen.com/subject/ilwvuhtx.html