Acwing 快排 归并 整理笔记

简介: Acwing 快排 归并 整理笔记

20f5b6f1ee93439a99cd254fa4d77a5c.png

快速排序:

快排板子分治思想

1.确定分界点(x = a[l+r>>1]),这么做是为了避免有序的情况下,子问题规模依旧较大的问题(如果有序且分界点取在首个,那么数组被分为长度1和n-1)

2.调整区间,使得第一个区间<=x,第二个区间>=x;

3.递归两个区间

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e5+10;
int a[N];
void quicksort(int l,int r,int a[])
{
    if (l>=r) return;
    int i = l-1,j = r+1,x = a[i+j>>1];
    while (i<j)
    {
        do i++;while (a[i]<x);
        do j--;while (a[j]>x);
        if (i<j) swap(a[i],a[j]);
    }
    quicksort(l,j,a);
    quicksort(j+1,r,a);
}
int main()
{   
    int n;
    scanf("%d",&n);
    for (int i = 0;i<n;i++) scanf("%d",&a[i]);
    quicksort(0,n-1,a);
    for (int i = 0;i<n;i++) printf("%d ",a[i]);
    return 0;
}

归并排序


20ab39b2b4f04a1f8dd3705810a065ad.png


1:确定分界点

2:递归

3:归并merge(注意可能一条链子输完了另一条还没有输完的情况)

归并板子

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e5+10;
int tmp[N];//临时容器
int a[N];
void mergesort(int l,int r,int a[])
{
    if (l>=r) return ;
    int mid = l+r>>1;//划分区间
    mergesort(l,mid,a);
    mergesort(mid+1,r,a);//递归排序
    int i = l,j = mid+1,k =0;
    while (i<=mid&&j<=r)//双指针
    {
        if (a[i]<=a[j]) tmp[k++] = a[i++];
        else tmp[k++] = a[j++];
    }
    while (i<=mid) tmp[k++] = a[i++];
    while (j<=r) tmp[k++] = a[j++];//收尾
    for (int i = l,j = 0;j<k;j++,i++) a[i] = tmp[j];//复制到到原数组
}
int main()
{   
    int n;
    scanf("%d",&n);
    for (int i = 0;i<n;i++) scanf("%d",&a[i]);
    mergesort(0,n-1,a);
    for (int i = 0;i<n;i++) printf("%d ",a[i]);
    return 0;
}

经典例题:逆序对的数量:acwing788

给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。

输入样例:

1. 6
2. 2 3 4 5 6 1

输出样例:

5

逆序对分成三块,前两块ans加上函数自身的递归,第三块先排序再累加;

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const LL N = 1e5+10;
LL a[N],tmp[N];
LL mergesort(LL l,LL r,LL a[])
{   
    if (l>=r) return 0;
    LL mid = l+r>>1;
    LL ans = 0;
    ans+=mergesort(l,mid,a)+mergesort(mid+1,r,a);
    LL i = l,j = mid+1,k = 0;
    while (i<=mid&&j<=r)
    {
        if (a[i]<=a[j]) tmp[k++] = a[i++];
        else
        {
            tmp[k++] = a[j++];
            ans += mid-i+1;
        }
    }
    while (i<=mid) tmp[k++] = a[i++];
    while (j<=r)   tmp[k++] = a[j++];
    for (LL i = 0,j = l;i<k;i++,j++)  a[j] = tmp[i];
    return ans;
}
int main()
{
    LL n;
    scanf("%ld",&n);
    for (int i = 0;i<n;i++) scanf("%ld",&a[i]);
    LL ans = mergesort(0,n-1,a);
    printf("%ld",ans);
    return 0;
}

24839e48d8354f78a2d6d4b36151c074.png


1cd7edfae477414eb259b78ee9896f5d.png


相关文章
|
6月前
|
算法
双指针算法(acwing)疑难讲解
双指针算法(acwing)疑难讲解
40 0
|
12月前
快排&超详细,Leetcode排序数组题目带你升华掌握(上)
快排&超详细,Leetcode排序数组题目带你升华掌握
56 0
|
12月前
|
测试技术 编译器 Shell
快排&超详细,Leetcode排序数组题目带你升华掌握(下)
快排&超详细,Leetcode排序数组题目带你升华掌握(上)
134 0
|
JavaScript 前端开发
leetcode每日一题 2021/4/5 88. 合并两个有序数组
leetcode每日一题 2021/4/5 88. 合并两个有序数组
40 0
|
算法 搜索推荐
【第四天】算法图解 之 快速排序
【第四天】算法图解 之 快速排序
【第四天】算法图解 之 快速排序
|
算法 Java 测试技术
Leetcode刷题笔记:二分查找算法
LeetCode 对于数组查询算法之一的二分查找算法的简单认识。
101 0
|
算法 搜索推荐
LeetCode算法小抄--快速排序详解及应用
LeetCode算法小抄--快速排序详解及应用
|
算法 搜索推荐
算法笔记(二)——快排,归并算法(做成模板题)
算法笔记(二)——快排,归并算法(做成模板题)
算法笔记(二)——快排,归并算法(做成模板题)