问题
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。 并将P对1000000007取模的结果输出。 即输出P%1000000007
- 分治和递归。将序列每次折半划分成两个子数组,对应两个子问题。两个子问题解决了,即得到子序列的逆序对数量之后,再统计分别在两个子序列的逆序对的数量,加起来就是原问题的逆序对数量。
- 归并排序。如果两个子序列都是已经排好序的,统计分别在两个子序列的逆序对的数量就有复杂度低的方法,那么就需要对已经拍好序的两个子序列合并成一个排好序的序列,这其实就是归并排序要做的。
难点在于如何在归并过程中统计分别在两个子序列的逆序对的数量。核心代码:左子序列left..mid
,右子序列mid+1..high
,i和j分别是左、右子序列上的指针。
- 其中
mid-i+1
是左子序列上与右子序列的元素nums[j]
形成逆序对的所有元素数量,即i..mid
位置的元素,将其标记为x(j)。那么只要把右子序列所有元素的x(j)计算并求和即可得到所有逆序对的数量。- x(j)是互斥且完备的。
x(j)=mid-i+1
的理解:当要添加nums[j]
到辅助数组时,说明nums[i]>nums[j]
,且nums[i..mid]>nums[j]
,一共有mid-i+1
个逆序对。- 从小到大归并时,是从前往后的顺序,只能是计算x(j),也就是添加
nums[j]
时计算。若要计算x(j)进而求和获得左右子序列的逆序对数,那么需要从大到小归并,且从后向前的顺序。
- 从小到大归并时,是从前往后的顺序,只能是计算x(j),也就是添加
1 | while i <= mid and j <= high: |
完整代码如下:
1 | class Solution: |