zoukankan      html  css  js  c++  java
  • 逆序对

    给出一个算法,它能用O(nlgn)的最坏运行时间,确定n个元素的任何排列中逆序对的数目。(提示:修改合并排序)

    《算法导论》在这里直接提示修改合并排序,所以自然就是用到分治归并的思想,那么逆序对是出现在什么时候?出现多少呢?

    我们知道归并排序是通过分治,然后归并两个有序的序列成一个有序序列。现假设两段有序序列分别是[beg,mid]和[mid+1,end],在归并过程中(i,j分别为两段序列的下标),如果a[i]<a[j],则不会产生逆序对;但当a[i]>a[j]时,就出现逆序对了,出现了多少?既然[beg,mid]是有序的,那么[i-mid]序列就都能与a[j]构成逆序对,故:mid-i+1

    复杂度O(nlgn),代码如下:

    #include<iostream>
    using namespace std;
     
    /* 归并求逆序对数, arr 存储最终有序结果
     * 在函数外申请一个临时数组作为参数传入
     * 避免递归不断创建临时数组的开销
     */
    int Merge(int * arr, int beg, int mid, int end, int * tmp_arr)
    {
        memcpy(tmp_arr+beg,arr+beg,sizeof(int)*(end-beg+1));
        int i = beg;
        int j = mid + 1;
        int k = beg;
        int inversion = 0;  // 合并过程中的逆序数
        while(i <= mid && j <= end)
        {
            if(tmp_arr[i] <= tmp_arr[j])
            {
                arr[k++] = tmp_arr[i++];
            }else
            {
                arr[k++] = tmp_arr[j++];
                inversion += (mid - i + 1);
            }
        }
        while(i <= mid)
        {
            arr[k++] = tmp_arr[i++];
        }
        while(j <= end)
        {
            arr[k++] = tmp_arr[j++];
        }
        return inversion;
    }
     
    int MergeInversion(int * arr, int beg, int end, int * tmp_arr)
    {
        int inversions = 0;    // 记录倒序数
        if(beg < end)
        {
            int mid = (beg + end) >> 1;
            inversions += MergeInversion(arr, beg, mid, tmp_arr);
            inversions += MergeInversion(arr, mid+1, end, tmp_arr);
            inversions += Merge(arr, beg, mid, end, tmp_arr);
        }
        return inversions;
    }
     
    /* 测试序列 :answer: 10 */
    int testPoint[10] = {
        1, 4, 2, 9, 48,
       15, 13, 44, 6, 90
    };
     
    void main()
    {
        int arrcopy[10];      // 临时数组
        memcpy(arrcopy,testPoint,sizeof testPoint);
     
        printf("the num of inversions is: %d\n",
                MergeInversion(testPoint,0,9,arrcopy));
    }
  • 相关阅读:
    每日一水 POJ8道水题
    编译和使用 MySQL C++ Connector
    j2ee model1模型完成分页逻辑的实现 详解!
    DB查询分析器访问EXCEL时,要在表名前后加上中括弧或双引号
    指向结构体变量的指针
    EOSS V3.0 企业运营支撑系统(基于RBAC原理的权限管理)
    MybatisGen1.0 Mybatis JavaBean Mapper生成工具
    The table name must be enclosed in double quotation marks or sqare bracket while accessing EXCEL by
    资源-Android:Android
    软件-开发软件:Android Studio
  • 原文地址:https://www.cnblogs.com/sanfeng/p/4378149.html
Copyright © 2011-2022 走看看