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


相关文章
快排,做个笔记
static void Main(string[] args) { var list = new List() { 3, 4, 1, 2, 6, 5, 7 }; QuickSort(list, 0, list.
716 0
|
9月前
|
人工智能 BI
【每日一题】1. 牛客网——合并两个有序数组
【每日一题】1. 牛客网——合并两个有序数组
|
存储 算法 Java
LeetCode刷题88-简单-合并两个有序数组
LeetCode刷题88-简单-合并两个有序数组
147 0
LeetCode刷题88-简单-合并两个有序数组
|
程序员
leetcode二分查找问题整理
自从做完leetcode上的三道关于二分查找的题后,我觉得它是比链表找环还恶心的题,首先能写出bugfree代码的人就不多,而且可以有各种变形,适合面试的时候不断挑战面试者,一个程序猿写代码解决问题的能力都能在这个过程中考察出来。
1112 0
|
机器学习/深度学习 人工智能
|
算法 索引
LeetCode刷题day18(二分法)
LeetCode刷题day18(二分法)
|
9月前
|
算法
刷题专栏(七):将有序数组转换为二叉搜索树
刷题专栏(七):将有序数组转换为二叉搜索树
82 0
|
9月前
|
存储 算法 索引
LeetCode刷题---链表经典问题(双指针)
LeetCode刷题---链表经典问题(双指针)

热门文章

最新文章