快速排序:找出最大最小的前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);
}
}
来源:CSDN
作者:Worthy_Wang
链接:https://blog.csdn.net/Worthy_Wang/article/details/104143775