zoukankan      html  css  js  c++  java
  • 1.7 逆序数与归并排序[inversion pairs by merge sort]

    【本文链接】

    http://www.cnblogs.com/hellogiser/p/inversion-pairs-by-merge-sort.html

    【题目】

    编程之美1.7光影切割问题可以进一步将问题转化为求逆序数问题。

    【分析】

    求解逆序对问题与MergeSort类似,只需要对MergeSort稍作修改即可实现。MergeSort是采用分治法的思想,若需要排序A[p...r],则可以对半分成A[p...q]和A[q...r],然后将这有序的两部分Merge,而Merge的过程为Θ(n)的时间复杂度。根据主定率T(n)=2(Tn/2)+Θ(n),时间复杂度为T(n)=Θ(nlgn)。

    同理,求整个序列中的逆序对,也可以利用分治法的思想,即

    逆序对(A[p...r])= 逆序对(A[p...q])+逆序对(A[q...r])+逆序对(A[p...q], A[q...r]之间)

    结合MergeSort,关键是如何在Θ(n)的时间有效的求出A[p...q], A[q...r]之间的逆序对。因为在合并排序的Merge过程中,A[p...q]和A[q...r]已经有序,假设此时已经Merge到A[i...q]和A[j...r]。考虑接下来的一步:如果A[i]<=A[j],说明A[i]比后面的序列A[j...r]中的元素都小,不存在逆序对;如果A[i]>A[j],,则说明A[j]比前面的序列A[i...q]都小,即以j结尾的逆序对的数量为前面的序列剩余序列A[i...q]中元素的数量。

    Merge的过程中即可得到A[p...r], A[r...q]之间的逆序对的数量,时间复杂度亦为Θ(n), 由主定律总的时间复杂为 Θ(nlgn),这种方法要比朴素的方法 Θ(n*n)好很多。

    【MergeSort】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/6/25
    */

    void merge(int *A, int p, int q, int r)
    {
        
    //Li: p...q           Rj: q+1...r
        int n1 = q - p + 1;
        
    int n2 = r - (q + 1) + 1;
        
    int *L = new int[n1 + 1];
        
    int *R = new int[n2 + 1];
        
    // copy L and R
        for (int i = 0; i < n1; i++)
            L[i] = A[p + i];
        
    for (int j = 0; j < n2; j++)
            R[i] = A[q + 
    1 + j];
        
    // mark end
        L[n1] = INT_MAX;
        R[n2] = INT_MAX;
        
    int i = 0// left
        int j = 0// right
        int k = 0// whole
        for (k = p; k <= r; k++)
        {
            
    if (L[i] <= R[j])
            {
                A[k] = L[i];
                i++;
            }
            
    else
            {
                
    // L[i]>R[j]
                A[k] = R[j];
                j++;
            }
        }

        
    delete []L;
        
    delete []R;
    }

    void merge_sort(int *A, int p, int r)
    {
        
    if (p < r)
        {
            
    int q = (p + r) / 2;
            merge_sort(A, p, q);
            merge_sort(A, q + 
    1, r);
            merge(A, p, q, r);
        }
    }

    void MergeSort(int *A, int n)
    {
        merge_sort(A, 
    0, n - 1);
    }

    [InversionPair]

     inversionPair只需要在merge函数中增加3行代码记录即可。先将inversion_pairs初始化为0,当L[i]>R[j]时,更新inversion_pairs=inversion_pairs+(n1-i),最后返回即可。同时在merge_sort中返回left_pair,right_pair和corss_pair之和即可。

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/6/25
    */

    int merge_pair(int *A, int p, int q, int r)
    {
        
    //Li: p...q           Rj: q+1...r
        int n1 = q - p + 1;
        
    int n2 = r - (q + 1) + 1;
        
    int *L = new int[n1 + 1];
        
    int *R = new int[n2 + 1];
        
    // copy L and R
        for (int i = 0; i < n1; i++)
            L[i] = A[p + i];
        
    for (int j = 0; j < n2; j++)
            R[i] = A[q + 
    1 + j];
        
    // mark end
        L[n1] = INT_MAX;
        R[n2] = INT_MAX;
        
    int i = 0// left
        int j = 0// right
        int k = 0// whole
        //============================
        int inversion_pairs = 0;
        
    //============================
        for (k = p; k <= r; k++)
        {
            
    if (L[i] <= R[j])
            {
                A[k] = L[i];
                i++;
            }
            
    else
            {
                
    // L[i]>R[j]
                A[k] = R[j];
                j++;
                
    //============================
                inversion_pairs += (n1 - i);
                
    //============================
            }
        }

        
    delete []L;
        
    delete []R;
        
    //============================
        return inversion_pairs;
        
    //============================
    }

    int inversion_pair(int *A, int p, int r)
    {
        
    if (p < r)
        {
            
    int q = (p + r) / 2;
            
    //======================================
            int left_pair = inversion_pair(A, p, q);
            
    int right_pair = inversion_pair(A, q + 1, r);
            
    int cross_pair = merge_pair(A, p, q, r);
            
    return left_pair + right_pair + cross_pair;
            
    //======================================
        }
        
    else
            
    return 0;
    }

    int InversionPair(int *A, int n)
    {
        
    return inversion_pair(A, 0, n - 1);
    }

    【链接】

    http://www.cnblogs.com/bovine/archive/2011/09/22/2185006.html

    http://blog.csdn.net/zhanglei8893/article/details/6230233

    【本文链接】

    http://www.cnblogs.com/hellogiser/p/inversion-pairs-by-merge-sort.html

    个人学习笔记,欢迎拍砖!---by hellogiser

    Author: hellogiser
    Warning: 本文版权归作者和博客园共有,欢迎转载,但请保留此段声明,且在文章页面明显位置给出原文连接。Thanks!
    Me: 如果觉得本文对你有帮助的话,那么【推荐】给大家吧,希望今后能够为大家带来更好的技术文章!敬请【关注】
  • 相关阅读:
    java-集合框架-泛型2-泛型限定
    进程间通信
    多进程编程基础概念
    linux deb 打包流程
    linux RPM 打包流程
    Python 第一個程序
    从注册验证码入手,我保住了30%的流失用户
    为什么Web端登录需要验证码?
    网络验证码的进化:从简单图文到无感验证
    公开课 | 金融知识图谱的应用探索
  • 原文地址:https://www.cnblogs.com/hellogiser/p/inversion-pairs-by-merge-sort.html
Copyright © 2011-2022 走看看