目录
时间复杂度不特别说明的情况下,指平均情形的复杂度
排序在算法竞赛中常见的应用
1.
观察出目标具有某种性质,使用
std::sort
排序,然后贪心
2.
归并排序求逆序对,
cdq
分治
3.
基数排序,后缀数组
4.
个元素放在 个位置,不同摆法有不同结果,答案要求取所有结果中最值,做法是比较两个元
素交换前后的结果变化,如果变化朝着目标去,就交换,否则不交换
以下排序目标都是升序数组都从0 开始存放数据,数组长度都为n开头都有如下代码const int N = 1e6+10 ;int a [ N ];swap函数表示交换两个数据
冒泡 选择 插入三件套(时间复杂度大:n^2)
平时运用这些排序方法没有问题,算法竞赛就有可能会超时
//冒泡排序
for (int j = 0; j < n; j++) {
for (int i = 1; i < n - j - 1; i++) {
if (a[i] > a[i + 1]) {
swap(a[i], a[i + 1]);
}
}
}
//选择排序
for (int i = 0; i < n; i++) {
int temp = i;
for (int j = 0; j < n; j++) {
if (a[temp] > a[j])
temp = j;
}
swap(a[i], a[temp]);
}
//插入排序
for (int i = 0; i < n; i++) {
for (int j = i - 1; j >= 0 ; --j)
{
if(a[j]>a[j+1])
swap(a[j], a[j + 1]);
}
}
归并排序(时间复杂度:O(n*log2 n)
主要运用归并来计算逆序对的数量
直接上洛谷逆序对原题链接
https://www.luogu.com.cn/problem/P1908
void merge_sort(int q[], int l, int r)//归并基本思路
{
if (l >= r)return;
int mid = l + r >> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid+1;
while (i <= mid && j <= r)
{
if (q[i] <= q[j]) tmp[k++] = q[i++];
else tmp[k++] = q[j++];
}
while (i <= mid)tmp[k++] = q[i++];
while (j <= r) tmp[k++] = q[j++];
for (i = l, j = 0; i <= r; i++, j++)q[i] = tmp[j];
}
快速排序(用的最多)
它的最坏情形的性能为O(n^2),但稍加努力就可避免这种情形。
和归并一样运用递归的思路
可以直接套用这个函数直接做题
void quick_sort(int q[], int l, int r)
{
if (l >= r)return;
int mid = q[l + r >> 1];
int i = l - 1, j = r + 1;
while (i < j)
{
do i++; while (q[i] < mid);
do j--; while (q[j] > mid);
if (i < j)swap(q[i], q[j]);
}
quick_sort(q, l, j); quick_sort(q, j + 1, r);
}