数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
- 0 <= 数组长度 <= 50000
解法:最容易想到的暴力法,将元素和后面的元素一个一个的进行比较,但是这种方法的时间复杂度是O(n*n)超时。
可以使用递归排序的帮助进行计算。在递归的过程中如果前面的一个元素放下来了,后半部分有几个元素就有几个逆序对。
class Solution {
public:
int reversePairs(vector<int>& nums) {
if(nums.empty())
return 0;
vector<int> copy(nums);
return reversePairsCore(nums,copy,0,nums.size()-1);
}
int reversePairsCore(vector<int>& nums,vector<int>& portionOrder,int low,int high){
if(low == high)
return 0;
int length = (high - low) / 2;
// 为了将nums变得局部有序,将其传递给portionOrder,经过递归处理以后nums前半部分将变得局部有序
int leftCount = reversePairsCore(portionOrder,nums,low,low+length);
// 为了将nums变得局部有序,将其传递给portionOrder,经过递归处理以后nums后半部分将变得局部有序
int rightCount = reversePairsCore(portionOrder,nums,low+length+1,high);
int i = low+length;
int j = high;
int copyIndex = high;
int count = 0;
while(i>=low && j>=low+length+1){
if(nums[i]>nums[j]){
portionOrder[copyIndex--] = nums[i--];
count += j - (low + length); // 后半部分还剩几个就是有几个逆序对
} else
portionOrder[copyIndex--] = nums[j--];
}
while (i>=low)
portionOrder[copyIndex--] = nums[i--];
while(j >= low+length+1)
portionOrder[copyIndex--] = nums[j--];
// 经过上面一系列的处理后portionOrder数组在low~high这一部分已经是有序的了
return count + leftCount + rightCount;
}
};
``