这是我参与「第五届青训营 」伴学笔记创作活动的第-2 天
- 快速排序求第k小的数
#include<iostream>
using namespace std;
const int N = 1e5+10;
int q[N],n,k;
int quick_sort(int l, int r, int k){
if(l>=r) return q[l];
int i=l-1,j=r+1,x=q[l];
while(i<j){
while(q[++i]<x);
while(q[--j]>x);
if(i<j) swap(q[i],q[j]);
}
int s = j-l+1;
if(s>=k) return quick_sort(l,j,k);
else return quick_sort(j+1,r,k-s);
}
int main(){
cin>>n>>k;
for(int i=0;i<n;i++) cin>>q[i];
int res = quick_sort(0,n-1,k);
cout<<res<<endl;
}
如果求第k大的数只需修改快排比较部分,改为从大到小的排序。即
while(q[++i]>x);
while(q[--j]<x);
2. 归并排序求逆序对数
思路:利用归并分治递归的思想,逆序对分布有三种情况:第一是全部在左边,第二是全部在右边,第三是第一个数在左边,第二个数在右边。前两个情况递归去找就行了,第三种在归并最后合并的时候,当q[i]>q[j], q[i,mid]>q[j]。这时有mid-i+1个逆序对。
#include<iostream>
using namespace std;
const int N = 1e5+10;
int q[N],tmp[N];
typedef long long ll;
ll merge_sort(int q[], int l, int r){
if(l>=r) return 0;
int mid = l+r>>1;
ll res = merge_sort(q,l,mid) + merge_sort(q,mid+1,r);
int i=l, j=mid+1, k=0;
while(i<=mid && j<=r){
if(q[i]<=q[j]) tmp[k++]=q[i++];
else{
// q[i,mid]>q[j]
tmp[k++]=q[j++];
res += mid-i+1;
}
}
while(i<=mid) tmp[k++]=q[i++];
while(j<=r) tmp[k++]=q[j++];
for(int i=l,k=0;i<=r;i++,k++) q[i]=tmp[k];
return res;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>q[i];
ll res = merge_sort(q,0,n-1);
cout<<res<<endl;
return 0;
}