zoukankan      html  css  js  c++  java
  • 归并排序——逆序对

    归并排序

      归并排序,顾名思义,是一种排序算法。速度应该不错(由于长期sort我就只知道sort最快[狗头]),实际上他的思想是分治。

      分治分治,分而治之。那么对于一个数的序列怎么去分而治之呢?如果我们面对目前两个数列:1 2 3 和 4 5 6。将这两个接在一起形成一个有序的序列,是十分简单的。直接将它们接在一起就行了。所以说分,是分成两部分,由于分治的基本思想就是我的子问题先解决再轮到我,所以这两个序列肯定是有序的。

      当然算法主要是解决那些毒瘤情况(而非上文中的超简单例子)。面对这个:1 4 5和2 3 6。这种例子肯定不是那么好拼的,那么我们分别用两个指针,一个新的答案数组。这两个指针分别指向这两个序列中的数。然后比较,谁小谁先进答案数组,直到完为止。是不是很简单呢?

    逆序对——归并排序的实际应用

      逆序对,是指 i<j且ai>aj这样的情况。怎么求出逆序对就是归并排序要做的事情。

      对于一个数列,它的逆序对由两个子序列中的逆序对以及跨子序列的逆序对组成。很显然,两个子序列中的答案早以计算好(分治特性)。那么如何求出“跨区间”的逆序对呢?

      在归并排序两个指针对比的时候,我们可以找到它们之间的大小关系。记两指针分别为i j 如果 ai<=aj,那么对答案没有影响。否则的话就意味着逆序对出现。由于子序列满足有序,所以有i~序列末尾 的数都比aj大,也就是同时出现了多个逆序对,直接加上这么多个答案就行了。

    code

    void gb(int l,int r){
        if(l==r)return;
        else{
            int mid=(l+r)>>1,p=0;
            gb(l,mid);gb(mid+1,r);
            int i=l,j=mid+1;
            while(i<=mid&&j<=r){
                if(a[i]<=a[j]){
                    c[++p]=a[i];
                    i++;
                }
                else{
                    c[++p]=a[j];
                    j++;
                    ans+=(mid-i+1);
                }
            }
            while(i<=mid)c[++p]=a[i++];
            while(j<=r)c[++p]=a[j++];
            for(i=1;i<=p;++i){
                a[l+i-1]=c[i];
            }
        }
    }
    View Code
  • 相关阅读:
    Bootstrap_让Bootstrap轮播插件carousel支持左右滑动手势的三种方法
    JAVA_用Java来获取访问者真实的IP地址
    Html5_移动前端不得不了解的html5 head 头标签
    ThinkPad_T430重装系统
    JavaScript_JS判断客户端是否是iOS或者Android
    Html5_禁止Html5在手机上屏幕页面缩放
    HttpClient_httpclient 4.3.1 post get的工具类
    HttpClient_使用httpclient必须知道的参数设置及代码写法、存在的风险
    LATEX数学公式基本语法
    为WLW开发Latex公式插件
  • 原文地址:https://www.cnblogs.com/clockwhite/p/11623252.html
Copyright © 2011-2022 走看看