美文网首页ACM算法题
数据结构实验之排序五:归并求逆序数

数据结构实验之排序五:归并求逆序数

作者: YellowTag | 来源:发表于2018-10-01 11:50 被阅读0次

Problem Description

对于数列a1,a2,a3…中的任意两个数ai,aj (i < j),如果ai > aj,那么我们就说这两个数构成了一个逆序对;在一个数列中逆序对的总数称之为逆序数,如数列 1 6 3 7 2 4 9中,(6,4)是一个逆序对,同样还有(3,2),(7,4),(6,2),(6,3)等等,你的任务是对给定的数列求出数列的逆序数。

Input

输入数据N(N <= 100000)表示数列中元素的个数,随后输入N个正整数,数字间以空格间隔。

Output

输出逆序数。

Sample Input

10
10 9 8 7 6 5 4 3 2 1

Sample Output

45

思路

首先我们清楚的是逆序对这个概念,很容易理解,其实我们选择用选择排序都能来做这道题,但是时间上肯定是不行的
然后我们想想前面已经说过的一些排序,快排?好像不行,不知道从哪里插入一串代码从而能够计数逆序对的个数。
堆排序?好像也不可以
为了保证时间复杂度比较小,而且也能满足这个需求,我们就采用归并排序:
我们来看看归并排序

void sort(int arr[],int left,int right){
    if(left>=right)
        return;
    else{
        int mid; 
        mid=(left+right)/2;
        sort(arr,left,mid);//对左边排序 
        sort(arr,mid+1,right);//对右边排序
        merge(arr,left,mid,right,temp);
      }
  }
void merge(int arr[],int left,int mid,int right,int temp[]){
    int i=left;
    int j=mid+1;
    int t=0;        
    while(i<=mid&&j<=right){
        if(arr[i]<arr[j])
            temp[t++]=arr[i++];
        else{          
            temp[t++]=arr[j++];     
            sum+=mid-i+1;//逆序对的个数 
        }
       }//看做是两副牌花色向上的牌,不断拿走第一张,直到最后一副牌为空 ,注意要考虑相等的情况(这种小细节尤为重要,如果没考虑相等,那么这个元素就不会被保存) 
    while(i<=mid)
        temp[t++]=arr[i++];//我们要把两副牌其中一幅不是空的所有牌都放到temp中,注意,这两幅牌肯定已经排好序了,可以自己推导为什么 
    while(j<=right)
        temp[t++]=arr[j++];//这里如果用if语句就多此一举了    ,要记住while也算是一种条件语句而且循环 
    
    //然后我们把合并并且排好序了的牌全部放回arr中
    t=0;
    while(left<=right)      
        arr[left++]=temp[t++];             
   }

其实很简单,就是采用分治法的思想,然后再往上合并,这里就不多讲了,可以慢慢看一下代码,仔细思考一下

那么怎么去求逆序对呢?

我们就是要去利用合并的操作,在合并时,我们把两个分支看作两堆牌,而且要知道,这样两堆牌肯定是排好序了的,然后我们把两堆各自第一张牌(从小到大排序),进行比较,如果出现大于关系的话,说明接下来这一堆牌都会比那一张大,所以逆序对就是下面这一堆牌的数量

要注意的就是要考虑等于的情况,等于肯定是不算逆序对,所以在if else那个地方要注意是小于等于

题破:

#include<stdio.h>
#include<iostream>
  using namespace std;
  int a[100010];
  int temp[100010];
  long long sum=0;
  void sort(int arr[],int left,int right);
  void merge(int arr[],int left,int mid,int right,int temp[]);
  int main(){
    int t;
    scanf("%d",&t);
    for(int i=0;i<t;i++)
    scanf("%d",&a[i]);      
    sort(a,0,t-1);      
    printf("%lld\n",sum);   
  }
  void sort(int arr[],int left,int right){
    if(left>=right)
        return;
    else{
        int mid; 
        mid=(left+right)/2;
        sort(arr,left,mid);//对左边排序 
        sort(arr,mid+1,right);//对右边排序
        merge(arr,left,mid,right,temp);
      }
  }
   void merge(int arr[],int left,int mid,int right,int temp[]){
    int i=left;
    int j=mid+1;
    int t=0;        
    while(i<=mid&&j<=right){
        if(arr[i]<=arr[j])
            temp[t++]=arr[i++];
        else{          
            temp[t++]=arr[j++];     
            sum+=mid-i+1;//逆序对的个数 
        }
       }//看做是两副牌花色向上的牌,不断拿走第一张,直到最后一副牌为空 ,注意要考虑相等的情况(这种小细节尤为重要,如果没考虑相等,那么这个元素就不会被保存) 
    while(i<=mid)
        temp[t++]=arr[i++];//我们要把两副牌其中一幅不是空的所有牌都放到temp中,注意,这两幅牌肯定已经排好序了,可以自己推导为什么 
    while(j<=right)
        temp[t++]=arr[j++];//这里如果用if语句就多此一举了    ,要记住while也算是一种条件语句而且循环 
    
    //然后我们把合并并且排好序了的牌全部放回arr中
    t=0;
    while(left<=right)      
        arr[left++]=temp[t++];             
   }
/***************************************************
52
User name: lin99
53
Result: Accepted
54
Take time: 44ms
55
Take Memory: 984KB
56
Submit time: 2018-09-15 16:42:48
57
****************************************************/

相关文章

  • 排序算法

    常考排序 快速排序 归并排序 归并排序求逆序数对 堆排序 堆排序是指利用堆这种数据结构所设计的一种排序算法。 堆积...

  • 数据结构实验之排序五:归并求逆序数

    Problem Description 对于数列a1,a2,a3…中的任意两个数ai,aj (i < j),如果a...

  • POJ 1804

    POJ 1804 题意 求逆序数 思路 在网上看到可以用归并排序,由于数据较小,可以直接求。

  • 排序算法-堆排序

    参考: Java排序算法(五):堆排序 【算法与数据结构】图说堆排序 【数据结构】排序算法:希尔、归并、快速、堆排...

  • ologn排序算法后的两个问题

    求一个数组的逆序数对的个数(归并排序) 求出nums里第k小的数(快速排序)

  • php常用的排序算法与二分法查找

    一 : 归并排序 将两个的有序数列合并成一个有序数列,我们称之为"归并"。归并排序(Merge Sort)就是利用...

  • 归并排序

    归并排序是利用归并的思想对数列进行排序。--将两个有序数列合并成一个有序数列,称之为“归并”,归并包括从上往下和从...

  • 算法 | 归并排序

    归并排序 归并排序算法的核心就是 “归并”,将两个有序的数列合并,形成更大的有序数组。 归并排序的原理 上面说了,...

  • 归并排序

    归并排序的基本思路: merge函数将两个有序数列归并到一个有序数列中 根据分治法,利用递归,不断归并有序数列 递...

  • 面试题总结

    算法思维 简述归并排序归并排序是一个使用分治策略来对乱序数组进行排序的算法,使用的思想是将乱序数组不断切割分解成若...

网友评论

    本文标题:数据结构实验之排序五:归并求逆序数

    本文链接:https://www.haomeiwen.com/subject/hkqnoftx.html