zoukankan      html  css  js  c++  java
  • [jobdu]数组中的逆序对

    http://ac.jobdu.com/problem.php?pid=1348 数组中的逆序对也是个常见的题目,算法导论中也有一些描述,参考:http://www.cnblogs.com/wuyuegb2312/p/3156286.html。解法自然有朴素解法O(n^2)不表,然后有基于归并排序的,可以O(n*logn)。

    1.在归并排序中,同样是对一个数组分为两段处理,在处理这两段时,并不会影响右段元素与左段元素的逆序关系,只有在归并时才会改变。
    2.归并时的改变方式和插入排序是类似的:右段中取出元素放在左段其余所有元素前面时,相当于左段整体后移,后移的元素数就是这个逆序数。
    3.由于归并排序使用的是分治法,将每次归并的逆序数累加,最后结果就是总的逆序数。并且,归并排序的时间复杂度是O(nlogn),优于插入排序。
    根据以上的探讨,归并排序稍作修改,就获得了时间复杂度为O(nlogn)的寻找逆序对总数的算法了。

    本来也到此结束了,后来又发现一个基于树状数组的解法(http://boj.haotui.com/thread-2792-1-1.html),不过还是太高级,就不深入研究了。树状数组略看了一下,和数字的和有关,比如可以解决多数求和的问题。“采用累加的方法还有一个局限,那就是,当修改掉数组中的元素后,仍然要你求数组中某段元素的和,就显得麻烦了。所以我们就要用到树状数组,他的时间复杂度为O(lgn)。”(http://www.cnblogs.com/zhangshu/archive/2011/08/16/2141396.html

    具体代码:

    1.C++中的数组新建和删除是 int* arr = new int[n]; delete arr[];
    2.出现HEAP CORRUPTION DETECTED往往是操作new申请的内存溢出。比如我一开始调用了mergeCount(0, n)就错误的访问了a[n]。 http://blog.sina.com.cn/s/blog_511703010100lz33.html

    3.借鉴了别人的写法,在一个循环里就把双指针移动写完了,主要是把到头后的判断加上,一开始使用||。
    4.因为mergeSort的空间复杂度是o(n),所以也可以一开始就申请好数组,就不用在递归里不断new和delete了。
    5.mergeCount的时候,当右边的小于左边的时,要注意计算对逆序数目。

    #include <cstdio>
    using namespace std;
    long long tot;
    int a[100005];
    void mergeCount(int l, int r) // [l, m], [m+1, r]
    {
        if (l >= r) return;
        int m = (l + r) / 2;
        mergeCount(l, m);
        mergeCount(m+1, r);
        int* tmp = new int[r-l+1];
        int i = l;
        int j = m+1;
        int k  = 0;
        while (i <= m || j <= r)
        {
            if (i > m)
            {
                tmp[k++] = a[j++];
            }
            else if (j > r)
            {
                tmp[k++] = a[i++];
            }
            else if (a[i] <= a[j])
            {
                tmp[k++] = a[i++];
            }
            else
            {
                tmp[k++] = a[j++];
                tot += (m-i+1);
            }
        }
        for (int j = 0; j <= (r - l); j++)
        {
            a[l+j] = tmp[j];
        }
        delete[] tmp;
    }
       
    int main()
    {
        int n;  
        while(scanf("%d", &n) == 1)  
        {  
            for(int i=0; i<n; ++i)  
                scanf("%d", &a[i]);              
            tot = 0;  
            mergeCount(0, n-1);  
            printf("%lld
    ", tot);  
        }  
    }
    

      

  • 相关阅读:
    JS转义 escape()、encodeURI()、encodeURIComponent()区别详解
    PHP解决搜索时在URL地址栏输入中文字符搜索结果出现乱码
    CMSPRESS-PHP无限级分类2
    CMSPRESS-PHP无限级分类
    HTML5-CSS3-JavaScript(3)
    HTML5-CSS3-JavaScript(2)
    HTML5-CSS3-JavaScript(1)
    CSS3-Hover 效果 展示
    JAVA Socket地址绑定
    JAVA Socket无参构造方法的使用
  • 原文地址:https://www.cnblogs.com/lautsie/p/3276703.html
Copyright © 2011-2022 走看看