排序 二分学习
AcWing基础课学习
排序
1. 快速排序
1. 原理
对于一段无序的数列,若要将其排序,可以以此步骤进行:
- 对于一段的数列,可以先任取一点
mid
作为判断点。(其中mid
一般为数列中点) - 对于这段数列进行一次遍历,将大于
mid
的数放于右端,小于mid
的数放于左端。 - 然后对于分配过的序列,选取其
[l,p]
,[p+1,r]
两个子段继续上述操作,直到长度为1
。(其中p
为上述左右两端的分界点)
2. 具体实现(代码)
本代码思路参考自y总
void quick_sort(int a[],int l,int r){ if(l>=r) return;//设置退出条件 int i=l-1,j+1,mid = a[l+r>>1];//设置判断点 while(i<j){ do i++;while(a[i]<mid); do j--;while(a[j]>mid); if(i<j) swap(a[i],a[j]); } quick_sort(a,l,j);//继续对子段排序 quick_sort(a,j+1,r); }
- 时间复杂度:O(N*logN)
3. 相关题目
2. 归并排序
1. 原理
对于一段无序的数列,与快速排序相似,若要将其排序,可以以此步骤进行:
- 对于一段的数列,可以先任取一点
mid
作为分割点。(其中mid
一般为数列中点) - 先选取其
[l,mid]
,[mid+1,r]
两个子段继续排序,并假定其已经排序完成。 - 然后对于已经排序过的两段子段,按照排序顺序先放入
b
数组中,然后再将排序过的数列覆盖原数列。
2. 具体实现(代码)
本代码思路参考自y总
void merge_sort(int a[],int b[],int l,int r){ if(l>=r) return;//设置退出条件 int mid = l+r>>1,i=l,j=mid+1,k=0;//设置分割点 merge_sort(a,b,l,mid);merge_sort(a,b,mid+1,r);//先对子段排序 while(i<=mid&&j<=r) if(a[i]<=a[j]) b[k++] = a[i++]; else b[k++] = a[j++]; while(i<=mid) b[k++]=a[i++]; while(j<=r) b[k++]=a[j++]; for(i=l,j=0;i<=r;i++,j++) a[i]=b[j]; }
- 时间复杂度:O(N*logN)
3. 相关应用
- 求逆序对
当用归并排序对数组进行排序时,可以发现,当出现a[i]>b[j]
时,即出现了逆序对,且对于当前a[j]
来说,会出现mid-i+1
个逆序对(即a[j]
与[i,mid]
共mid-i+1
个数配对组合成逆序对)。由此我们可以在排序时求出对应数列中存在的逆序对。
long long merge_sort(int a[],int b[],int l,int r){ if(l>=r) return 0; int mid = l+r>>1,i=l,j=mid+1,k=0; long long ans = merge_sort(a,b,l,mid)+merge_sort(a,b,mid+1,r); while(i<=mid&&j<=r) if(a[i]<=a[j]) b[k++] = a[i++]; else ans += mid-i+1,b[k++]=a[j++]; while(i<=mid) b[k++] = a[i++]; while(j<=r) b[k++] = a[j++]; for(i=l,j=0;i<=r;i++,j++) a[i]=b[j]; return ans; }
4. 相关题目
二分
1. 整数二分
1.1 算法原理
对于一个单调的队列,我们可以通过其单调的特性,对于要找到的数k
可以通过以下方法找到:
- 先确定寻找的范围
l
和r
- 当
l<r
时,先取范围中点mid
,将区间[l,r]
分为[l,mid]
和[mid+1,r]
(此时mid=l+r>>1
)或[l,mid-1]
和[mid,r]
(此时mid=l+r+1>>1
)- 然后,在
l<r
条件下,根据check(mid)
函数,对l
,r进行更新,直到l>=r
1.2 代码实现
本代码思路参考自y总
//将区间[l,r]分为[l,mid]和[mid+1,r] int bsearch_1(int l,int r){ while(l<r){ int mid = l+r>>1; if(check(mid)) r=mid; else l=mid+1; }return l; } //将区间[l,r]分为[l,mid-1]和[mid,r] int bsearch_2(int l,int r){ while(l<r){ int mid = l+r+1>>1; if(check(mid)) l=mid; else r=mid-1 } }
1.3 相关题目
2. 浮点数二分
2.1 算法原理
对于一个单调的队列,我们可以通过其单调的特性,与整数二分相似,对于要找到的数k
可以通过以下方法找到:
- 先确定寻找的范围
l
和r
- 当
r-l>eps
时,先取范围中点mid
,mid=(l+r)/2
- 然后,在
r-l>eps
条件下,根据check(mid)
函数,对l
,r
进行更新,直到r-l<=eps
2.2 代码实现
本代码思路参考自y总
double bsearch(double l,double r){ while(r-l>eps){ double mid = (l+r)/2; if(check(mid)) r=mid; else l=mid; }return l; }
2.3 相关题目
本文作者:Dreaife
本文链接:https://www.cnblogs.com/dreaife/p/16456841.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步