快速排序:找出最大最小的前K个数

一世执手 提交于 2020-02-03 05:17:33

快速排序:找出最大最小的前K个数


一.找出最小的k个数:

  • 利用快速排序的原理,partition函数会找出mid值,mid左边的数都比mid小,而mid右边的数都比mid大所以只要找出k==mid的情况即可找到topK的数
  • 时间复杂度:O(logn)* O(n) = O(nlogn)
    其中O(n)是从头到尾遍历的复杂度,O(logn)是进行partition的复杂度
  • 空间复杂度:O(n)
    其中temp容器的空间复杂度是O(n)

注意:用这种方法是不能有重复数字的

//小的在左,大的在右,
int partition_small(vector<int>& a, int beg, int end) {
	int i = beg, j = end;
	int key = a[i];
	while (i < j) {
		while (i < j && a[j] > key) j--;//由于排序过程中不能有重复数字,所以a[i]>key是否取等也就无所谓了
		if (i < j)
			a[i++] = a[j];
		else
			break;

		while (i < j && a[i] < key) i++;
		if (i < j)
			a[j--] = a[i];
		else
			break;
	}
	a[i] = key;
	return i;
}

void topK_small(vector<int>& a, int k) {
	if (a.size() < k || a.size()<=0)
		return;

	int beg = 0, end = a.size() - 1;
	vector<int> temp;
	for (int i = 0; i < a.size(); i++) {
		swap(a[0], a[i]);
		temp = a;
		if (partition_small(temp, beg, end) == k - 1) {
			for (int j = 0; j <= k - 1; j++)//打印
				cout << temp[j] << endl;
			break;//经过第一次排序已经找到前k大的数
		}
	}
}


二.找出最大的k个数:

  • 原理与找出最小的k个数类似。
    注意:用这种方法是不能有重复数字的
//大的在左,小的在右,
int partition_big(vector<int>& a, int beg, int end) {
	int i = beg, j = end;
	int key = a[i];
	while (i < j) {
		while (i < j && a[j] < key) j--;//由于排序过程中不能有重复数字,所以a[i]>key是否取等也就无所谓了
		if (i < j)
			a[i++] = a[j];
		else
			break;

		while (i < j && a[i] > key) i++;
		if (i < j)
			a[j--] = a[i];
		else
			break;
	}
	a[i] = key;
	return i;
}

void topK_big(vector<int>& a, int k) {
	if (a.size() < k || a.size() <= 0)
		return;

	int beg = 0, end = a.size() - 1;
	vector<int> temp;
	for (int i = 0; i < a.size(); i++) {
		swap(a[0], a[i]);
		temp = a;
		if (partition_big(temp, beg, end) == k - 1) {
			for (int j = 0; j <= k - 1; j++)//打印
				cout << temp[j] << endl;
			break;//经过第一次排序已经找到前k大的数
		}
	}
}

心得体会:
1.在写程序中犯的错误:

  • 如果操作2的结果要运用到下一次的操作1中,就会由于for循环执行的次数导致很容易出错;
    所以应当将操作2放在操作1之前,将两个操作看成一个整体,这样就不会出错
for(int i = 0; i <= size; i++){
	//操作1

	//操作2
}


测试用例:

void test1() {
	vector<int> a{2,1,1,2,2,1 };
	cout << partition_small(a, 0, a.size() - 1) << endl;
}

void test3() {
	vector<int> a{ 0,5,1,2,4,3,6,9,7,8 };
	for (int i = 1; i <= a.size(); i++) {
		cout << "前" << i << "小的数" << endl;
		topK_small(a, i);
	}
}

void test3() {
	vector<int> a{ 0,5,1,2,4,3,6,9,7,8 };
	for (int i = 1; i <= a.size(); i++) {
		cout << "前" << i << "大的数" << endl;
		topK_big(a, i);
	}
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!