zoukankan      html  css  js  c++  java
  • 剑指offer35:数组中的逆序对

    1 题目描述

      在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

    2 思路和方法

      利用归并排序的思想,先把数组分隔成子数组,先统计出子数组内部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对的数目。注意在合并两个已排序的子数组后,要更新数组。O(n*log(n))。

    3 C++核心代码

     1 class Solution {
     2 public:
     3     int InversePairs(vector<int> data) {
     4         if(data.size() <= 1)
     5             return 0;
     6         int count = 0;
     7         vector<int> copy(data); // 初始化
     8         InversePairsCore(data, copy, 0, data.size()-1,count);
     9         return count;
    10     }
    11 
    12     // 归并
    13     void InversePairsCore(vector<int> &data, vector<int> &copy, int start, int end, int &count){
    14         if(start>=end){
    15             return;
    16         }
    17         int mid = (start + end) /2;
    18         InversePairsCore(data,copy,start,mid,count);
    19         InversePairsCore(data,copy,mid+1,end,count);
    20 
    21         int copyIndex = end; // 将较大数字从后往前复制到辅助数组
    22         int i = mid;    // 前半段最后一个元素下标
    23         int j = end;    // 后半段最后一个元素下标
    24         while (i>=start && j>=mid+1) {
    25             if (data[j] < data[i]){     // 逆序
    26                 count += j - mid;
    27                 count %= 1000000007;    // 取模防止逆序对溢出
    28                 copy[copyIndex--] = data[i--];
    29             } else{
    30                 copy[copyIndex--] = data[j--];
    31             }
    32         }
    33 
    34         while (i>=start)
    35             copy[copyIndex--] = data[i--];
    36 
    37         while (j>=mid+1)
    38             copy[copyIndex--] = data[j--];
    39 
    40         for (int k = start; k <= end; ++k)
    41             data[k] = copy[k];
    42 
    43     }
    44 };
    View Code

    4 C++完整代码

     1 #include<iostream>
     2 using namespace std;
     3 //数组中的逆序对
     4 long long GetMergePairsBetween(int* arr,int* copy,int start,int mid,int end)
     5 {
     6     //合并两个子数组,并计算逆序对个数
     7     int final1 = mid;//第一个数组的最后一位
     8     int final2 = end;//第二个数组的最后一位
     9     int index = end;//辅助数组的最后一位
    10     long long count = 0;
    11     while(final1 >= start && final2 >= mid+1)//两个数组都没有处理完
    12     {
    13        if(arr[final1] > arr[final2])
    14        {
    15            //如果第一个数组的元素大于第二个数组的任何元素,
    16            //则第一个数组的元素一定大于第个数组中final2之前的所有元素
    17            count += (final2 - mid);
    18            //将final1处的元素拷贝至copy数组
    19            //index和final1都向前移动
    20            copy[index--] = arr[final1--];
    21        }
    22        else
    23        {
    24            //第一个数组的元素小于第二个数组的元素
    25            //第二个数组的元素拷贝至copy数组
    26            //并将index和final2前移
    27            copy[index--] = arr[final2--];
    28        }
    29     }
    30     while(final1 >= start)//第一个数组的元素没有处理完
    31     {
    32        copy[index--] = arr[final1--];
    33     }
    34     while(final2 >= mid + 1)//第一个数组的元素没有处理完
    35     {
    36        copy[index--] = arr[final2--];
    37     }
    38     for(int i = end; i > index;i--) 
    39         arr[i] = copy[i];
    40     return count;
    41 }
    42 long long GetMergePairs(int* arr,int* copy,int start,int end)
    43 {
    44     long long ret = 0;
    45     if(start < end)
    46     {
    47        int mid = start + ((end - start)>>1);
    48        ret += GetMergePairs(arr,copy,start,mid);
    49        ret += GetMergePairs(arr,copy,mid+1,end);
    50        ret += GetMergePairsBetween(arr,copy,start,mid,end);
    51     }
    52     return ret;
    53 }
    54 long long GetTotalPairs(int arr[],int n)
    55 {
    56     if(arr == NULL || n < 2)
    57        return 0;
    58     int* copy = new int[n];
    59     long long sum = GetMergePairs(arr,copy,0,n-1);
    60     delete[] copy;
    61     return sum;
    62 }
    63 int main()
    64 {
    65     int arr[] = {7,5,6,4};
    66     int ret = GetTotalPairs(arr,sizeof(arr)/sizeof(arr[0]));
    67     cout<<ret<<endl;
    68     system("pause");
    69     return 0;
    70 }
    View Code

    参考资料

    https://blog.csdn.net/zjwreal/article/details/88769617

    https://blog.csdn.net/DERRANTCM/article/details/46761051(图)

    https://blog.csdn.net/peiyao456/article/details/54645952(完整代码)

  • 相关阅读:
    bat命令2
    bat实现创建、复制、删除文件及文件夹
    bat命令1
    ckeditor使用教程
    统计SqlServer每张表内的数据量
    entiryFramework 事务控制
    jQuery验证控件jquery.validate.js使用说明
    asp.net中套用母版页之后的findcontrol
    SessionState
    窗体单例问题
  • 原文地址:https://www.cnblogs.com/wxwhnu/p/11421187.html
Copyright © 2011-2022 走看看