剑指offer35_数组中的逆序对_题解

数组中的逆序对

题目描述

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

输入描述

题目保证输入的数组中没有的相同的数字

输入

[1,2,3,4,5,6,7,0]

返回值

7

分析

方案一:归并排序

计算逆序数就发生在排序的过程中,利用了「排序」以后数组的有序性。

思想是「分治算法」,所有的「逆序对」来源于 3 个部分:

  • 左边区间的逆序对;
  • 右边区间的逆序对;
  • 横跨两个区间的逆序对。

代码

/**
1.时间复杂度:O(NlogN)
归并排序的时间复杂度,直接看递归树的结点个数
2.空间复杂度:O(N)
**/
class Solution
{
public:
    const int MOD = 1000000007;
    int mergeAndCount(vector<int> &data, int left, int mid, int right, vector<int> &temp)
    {
        for (int i = left; i <= right; i++)
        {
            temp[i] = data[i];
        }

        int i = left, j = mid + 1;

        int cnt = 0;
        for (int k = left; k <= right; k++)
        {
            //判断是否越界
            if (i == mid + 1)
            {
                data[k] = temp[j];
                j++;
            }
            else if (j == right + 1)
            {
                data[k] = temp[i];
                i++;
            }
            else if (temp[i] <= temp[j])
            {
                data[k] = temp[i];
                i++;
            }
            else
            {
                data[k] = temp[j];
                j++;
                //在j指向的元素归并回去的时候,计算逆序对的个数
                cnt = (cnt + (mid - i + 1)) % MOD;
            }
        }
        return cnt;
    }
    int reversePairs(vector<int> &data, int left, int right, vector<int> &temp)
    {
        if (left == right)
        {
            return 0;
        }

        int mid = left + (right - left) / 2;
        int leftPairs = reversePairs(data, left, mid, temp);
        int rightPairs = reversePairs(data, mid + 1, right, temp);

        // 如果整个数组已经有序,则无需合并
        if (data[mid] <= data[mid + 1])
        {
            return leftPairs + rightPairs;
        }

        int crossPairs = mergeAndCount(data, left, mid, right, temp);
        return (leftPairs + rightPairs + crossPairs) % MOD;
    }
    int InversePairs(vector<int> data)
    {
        int len = data.size();

        if (len < 2)
        {
            return 0;
        }

        vector<int> copy(data.begin(), data.end());
        vector<int> temp(len);

        return reversePairs(copy, 0, len - 1, temp);
    }
};
posted @ 2021-01-13 09:57  RiverCold  阅读(78)  评论(0)    收藏  举报