关于TOP K算法的由浅入深

10 篇文章 0 订阅

关于优化的思想,可以参见原文链接
总的来说,方法和时间复杂度如下:
全局排序,O(n*lg(n))

局部排序,只排序TopK个数,O(n*k)

堆,TopK个数也不排序了,O(n*lg(k))

分治法,每个分支“都要”递归,例如:快速排序,O(n*lg(n))

减治法,“只要”递归一个分支,例如:二分查找O(lg(n)),随机选择O(n)

TopK的另一个解法:随机选择+partition

另外再补充下代码部分

1.大小顶堆做法,不用priority_queue

#include <iostream>
#include <assert.h>
#include<vector>
#include<queue>

using namespace std;


class xiaodingdui {
private:
	void MoveDown(vector<int>& arr, int moveIndx, int arrLen) {
		int leafL = moveIndx * 2 + 1;
		int leafR = moveIndx * 2 + 2;
		int minIndx = moveIndx;

		if (leafL < arrLen) {
			minIndx = arr[leafL] < arr[moveIndx] ? leafL : moveIndx;
		}
		if (leafR < arrLen) {
			minIndx = arr[leafR] < arr[minIndx] ? leafR : minIndx;
		}
		if (minIndx != moveIndx) {
			swap(arr[moveIndx], arr[minIndx]);
			MoveDown(arr, minIndx, arrLen);
		}

		return;
	}
	void BuildHeap(vector<int>& arr) {
		for (int i = (arr.size() - 1) / 2; i >= 0; i--) {
			MoveDown(arr, i, arr.size());
		}

		return;
	}
public:
	vector<int> smallestK(vector<int>& arr, int k) {
		vector<int> ret;

		BuildHeap(arr);
		for (int i = 0; i < k; i++) {
			ret.push_back(arr[0]);
			swap(arr[0], arr[arr.size() - i - 1]);
			MoveDown(arr, 0, arr.size() - i - 1);
		}
		return ret;
	}
};

2.同样是大顶堆排序,priority_queue的实现,会用到额外的空间和数据拷贝,好处是省去了建堆的操作

//同样是大顶堆排序,priority_queue的实现,会用到额外的空间和数据拷贝,好处是省去了建堆的操作
class priority_queue_heap {
public:
	vector<int> smallestK(vector<int>& arr, int k) {
		vector<int> res;
		priority_queue<int> q;
		for (int a : arr) {
			q.push(a);
			if (q.size() > k)
				q.pop();
		}
		while (!q.empty()) {
			res.push_back(q.top());
			q.pop();
		}
		return res;
	}
};

3.//快排思想,减治法(注意,非分治)

class kuaipai {
public:
	vector<int> smallestK(vector<int>& arr, int k) {
		if (arr.size() == 0)return vector<int>{};
		int n = arr.size();
		if (n <= k)return arr;
		int left = 0;
		int right = arr.size() - 1;
		while (left <= right) {
			int mid = quicksort(arr, left, right);
			if (mid + 1 == k) {
				vector<int>result(arr.begin(), arr.begin() + mid + 1);
				return result;
			}
			else if (mid + 1 < k) {
				left = mid + 1;
			}
			else right = mid - 1;
		}
		return vector<int>{};
	}

	int quicksort(vector<int>&arr, int left, int right) {
		int labelVal = arr[left];
		while (left < right) {
			while (left < right && arr[right] >= labelVal)right--;
			arr[left] = arr[right];
			while (left < right && arr[left] <= labelVal)left++;
			arr[right] = arr[left];
		}
		arr[left] = labelVal;
		return left;
	}
};

另外暴力排序和计数排序等就不贴了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值