zoukankan      html  css  js  c++  java
  • 求排列的逆序数(分治)

    一个排列含有逆序的个数称为这个排列的逆序数。例如排列263451含有8个逆序(2,1),(6,3),(6,4),(6,5),(6,1),(3,1),(4,1),(5,1),因此该排列的逆序数就是8。

    例题: 求排列的逆序数
    笨办法: O(n2)
    分治O( nlogn) :
    1) 将数组分成两半,分别求出左半边的逆序数和右半边的逆序数
    2) 再算有多少逆序是由左半边取一个数和右半边取一个数构成(要求O(n)实现)
    2) 的关键: 左半边和右半边都是排好序的。比如,都是从大到小排序的。这样,左右半边只需要从头到尾各扫一遍,就可以找出由两边各取一个数构成的逆序个数
     
    #include <iostream>
    
    using namespace std;
    
    void Merge(int a[],int s,int mid,int e,int tmp[])
    {
        int p1=s,p2=mid+1,p3=0;
        while(p1<=mid && p2<=e)
        {
            if(a[p1]>=a[p2])
                tmp[p3++]=a[p1++];
            else
                tmp[p3++]=a[p2++];
        }
        while(p1<=mid)
            tmp[p3++]=a[p1++];
        while(p2<=e)
            tmp[p3++]=a[p2++];
        int cnt=0;
        for(int i=s; i<=e; i++)
            a[i]=tmp[cnt++];
    }
    
    int MergeSortCount(int a[],int s,int e,int tmp[])
    {
        int result=0;
        if(s<e)
        {
            int mid=s+(e-s)/2;
            result+=MergeSortCount(a,s,mid,tmp);
            result+=MergeSortCount(a,mid+1,e,tmp);
            int i=s,j=mid+1;
            while(i<=mid && j<=e)
            {
                if(a[i]<=a[j])
                    j++;
                else
                {
                    result+=e-j+1;
                    i++;
                }
            }
            Merge(a,s,mid,e,tmp);
        }
        return result;
    }
    
    int main()
    {
        int a[6]={2,6,3,4,5,1};
        int tmp[10]; //辅助数组
    
        int size=sizeof(a)/sizeof(int);
        cout<<MergeSortCount(a,0,size-1,tmp)<<endl;
    
        for(int i=0;i<size;i++)
            cout<<a[i]<<" ";
    
        return 0;
    }
    

  • 相关阅读:
    指针和数组的关系
    深入学习数组
    const关键字与指针
    野指针是什么
    指针带来的一些符号的理解
    指针的本质
    内存管理之堆
    内存管理之栈
    元类
    断点调式和面向对象进阶
  • 原文地址:https://www.cnblogs.com/zhanyeye/p/9746102.html
Copyright © 2011-2022 走看看