排序
快排
分治
-
选取分界点 q[l] q[r] q[l+r>>1] 随机选值
-
调整范围,
-
-
递归左右两边
平均复杂度: nlogn
实现思想
选取分界点,有四个典例,然后以分界点调整左右区间,有双指针 i = l-1 , j = r+1 如果满足q[i]<x则i++ ,如果q[j] >x则j-- ,如果停住则交换两数 , 先整体进行一次排序后,然后递归排序每一个区间;
算法模板
#include <iostream>
using namespace std;
const int maxn=1e6+5;
int q[maxn];
void quick_sort(int q[],int l,int r){
if(l>=r) return ;
int i=l-1; int j=r+1; int x=q[l+r>>1];
while(i<j){
do i++; while (q[i]<x);
do j--; while (q[j]>x);
if(i<j) swap (q[i] ,q[j]);
}
quick_sort(q,l,j);
quick_sort(q,j+1,r);
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&q[i]);
quick_sort(q,1,n);
for(int i=1;i<=n;++i) printf("%d ",q[i]);
return 0;
}
第k小的数
https://www.acwing.com/problem/content/788/
给定一个长度为 nn 的整数数列,以及一个整数 kk,请用快速选择算法求出数列从小到大排序后的第 kk 个数。
输入格式
第一行包含两个整数 nn 和 kk。
第二行包含 nn 个整数(所有整数均在 1∼1091∼109 范围内),表示整数数列。
输出格式
输出一个整数,表示数列的第 kk 小数。
数据范围
1≤n≤1000001≤n≤100000,
1≤k≤n1≤k≤n
输入样例:
5 3
2 4 1 5 3
输出样例:
3
AC思路
将k值当做物理地址的值,比如第5个数其实就是数组4的位置,第2个数就是数组1的位置
每次只需要判断k在左区间还是右区间,一直递归查找k所在区间
最后只剩一个数时,只会有数组[k]一个数,返回数组[k]的值就是答案
AC代码
#include <iostream>
using namespace std;
const int maxn=1e5+5;
int q[maxn];
int quick_sort(int q[],int l,int r,int k){//[l,r]区间中搜索第k小的数
if(l>=r) return q[l];
int i=l-1, j = r+1 ,x =q[l + r >>1];
while(i<j) {
do i++ ;while(q[i]<x);
do j-- ;while(q[j]>x);
if(i<j) swap(q[i],q[j]);
}
int index = j - l + 1;
if ( index >= k ) quick_sort(q,l,j,k);
else quick_sort(q,j+1,r,k-index);
}
int main(){
int n , k;
cin >> n >> k ;
for( int i=0;i < n; ++ i){
cin >> q[i];
}
cout<<quick_sort(q,0,n-1,k)<<endl;
return 0;
}