归并排序求逆序对 acwing例题代码

简介: 归并排序求逆序对 acwing例题代码

逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i < j 且 a[i] > a[j],则其为一个逆序对;否则不是。


怎么求逆序对呢,我们今天用归并排序来说,资资给我们讲的时候就说归并排序80%会考。我也不知道考没考,我缓考了。

emmm,归并排序大家可能记不太清了,我再给大家提一下。

所谓归并排序就是将一组数进行无数次分割,将它划分成一个个有序的区间,然后再将这一个个有序的区间一个个合并成有序的区间。


32.png

怎么划分?


那这就是一个二分的过程了。我们每次将一段数进行分开,我们在这里引入一个mid为中间位置,一直将l到mid进行分,直到mid=l,这说明他已经将一个个连续的区间划分成一个个独立的区间了。这样我们在一个个进行合并的时候由于我们划分成两个区间(即两个两个区间进行合并),并且每一个区间都是有序的。


实际上归并排序的交换次数就是这个数组的逆序对个数


我们可以这样考虑:


归并排序是将数列a[l,r]分成两半a[l,mid]和a[mid+1,r]分别进行归并排序,然后再将这两半合并起来。


在合并的过程中(设l<=i<=mid,mid+1<=j<=h),当a[i]<=a[j]时,并不产生逆序数;当a[i]>a[j]时,在前半部分中比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid+1-i。


因此,可以在归并排序中的合并过程中计算逆序数。

归并排序求逆序对其实就是在归并排序的基础上加上了一个统计逆序对的过程。


#include <bits/stdc++.h>
using namespace std;
int arr[100010];
int temp[100010];
long long merge_sort(int arr[],int l,int r)
{
    if(l >= r)
    {
        return 0;
    }
    long long cnt = 0;
    int mid = l + r >> 1;
    cnt += merge_sort(arr,l,mid);
    cnt += merge_sort(arr, mid + 1, r);
    int k = 0;
    int i = l;
    int j = mid + 1;
    while(i <= mid && j <= r)
    {
        if(arr[i] <= arr[j])
        {
            temp[k++] = arr[i++];
        }
        else
        {
            cnt += mid - i + 1;
            temp[k++] = arr[j++];
        }
    }
    while(i <= mid)
    {
        temp[k++] = arr[i++];
    }
    while(j <= r)
    {
        temp[k++] = arr[j++];
    }
    for(i = l,j = 0;i <= r;i++,j++)
    {
        arr[i] = temp[j];
    }
    return cnt;
}
int bubble_sort(int arr[], int len) {  
    int ans = 0;
    int i, j;  
    for (i = 0; i < len - 1; i++)          //外层循环控制趟数,总趟数为len-1
    {
        for (j = 0; j < len - 1 - i; j++)//内层循环为当前i趟数 所需要比较的次数
        {
            if (arr[j] > arr[j + 1])
            {
                ans++;
                swap(arr[j], arr[j + 1]);          
            }  
        }
    }
    return ans;
}  
int main()
{
    int n;
    cin>>n;
    for(int i = 0;i < n;i++)
    {
        cin>>arr[i];
    }
    cout<<merge_sort(arr,0,n-1)<<endl;
    // cout<<bubble_sort(arr,n)<<endl;
    // for(int i = 0;i < n;i++)
    // {
    //     cout<<arr[i]<<" ";
    // }
    return 0;
}
相关文章
|
8月前
蓝桥杯:桶排序 与 例题:算式问题
蓝桥杯:桶排序 与 例题:算式问题
46 0
|
7月前
|
算法 C++
剑指offer(C++)-JZ10:斐波那契数列(时间复杂度O(logn)解法)
剑指offer(C++)-JZ10:斐波那契数列(时间复杂度O(logn)解法)
|
10月前
|
人工智能 移动开发 机器人
蓝桥杯AcWing 题目题解 - 二分与前缀和、差分
蓝桥杯AcWing 题目题解 - 二分与前缀和、差分
105 0
|
算法 C++
快排例题——第k个数
做道简单一点的题巩固一下
【AcWing】归并排序及其应用
【AcWing】归并排序及其应用
52 0
|
算法 vr&ar C++
【AcWing】双指针算法
这一篇博客也用了双指针算法,同学们可以参考一下
76 0
(归并排序)AcWing 788. 逆序对的数量
(归并排序)AcWing 788. 逆序对的数量
59 0
完全背包例题(滚动数组)
完全背包例题(滚动数组)
93 0
多重背包例题
多重背包例题
72 0