在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
变种是 求每个位置往后的逆序数的数量,大致思路一致(详见之前的题解,求数组右边小于当前元素的数量)
思路:
归并排序,归并排序的过程之中,如果右边的有序子数组需要插入到左边子数组中的时候,就说明,当前插入的元素一定小于目前还没有被插入的左边数组中的元素,这就构成了一个个逆序对,计算此时还没有插入的左边数组的数量即可。
注:这个实现时间和空间复杂度都很烂。
class Solution {
public:
int count;
int reversePairs(vector<int>& nums) {
count = 0;
if(nums.size()==0)return 0;
mergeSort(nums);
return count;
}
void mergeSort(vector<int> &nums)
{
int len = nums.size();
if(len==1)return;
int mid = len/2;
vector<int> A;
vector<int> B;
for(int i = 0;i<mid;i++)
{
A.push_back(nums[i]);
B.push_back(nums[i+mid]);
}
if(mid*2!=len)B.push_back(nums[len-1]);
mergeSort(A);
mergeSort(B);
mergeTwoSortedArray(A,B,nums);
}
void mergeTwoSortedArray(vector<int> &A,vector<int> &B,vector<int> &nums)
{
int lenA = A.size();
int lenB = B.size();
//B数组中的元素向A中进行插入的时候,计算逆序的数量;
//问题在于插入的实现
nums.clear();
int i = 0;
int j = 0;
while(i<lenA&&j<lenB)
{
if(A[i]<=B[j])
{
nums.push_back(A[i]);
i++;
}
else
{
nums.push_back(B[j]);
count+=(lenA-i);
j++;
}
}
while(i<lenA)
{
nums.push_back(A[i]);
i++;
}
while(j<lenB)
{
nums.push_back(B[j]);
j++;
}
return;
}
};