数组中的逆序对
个人思路
题意
逆序对:存在i<j且A[i] > A[j]则称为逆序对
思路
暴力解法:遍历每一个元素,与其后面的元素作比较,统计逆序对的个数,复杂度为O(N2)
分治法:
- 划分:
- 对一个序列划分为左右两个子序列(当划分到最后只剩下两个元素时便可直接判断),逆序对的有三种存在情况:1.在左子序列中;2.在右子序列中;3.由左右子序列共同构成。
- 当划分到只剩下一个元素时,开始回溯合并
- 求解:左右子序的元素顺序遍历比较大小(即归并排序的比较)
- 合并:合并过程中左右子序均按升序排序,当出现左子序列元素值大于右子序列中的某个元素值时,此时左子序列中的该元素及其后面的所有元素,均可与右子序列中的这个元素构成逆序对
注意
- 求解逆序对的代码只比归并排序的代码多了一句,表示计算左子序列中的该元素及其后面的所有元素的个数
ans += R1 + 1 - i;
个人思路代码
class Solution {
//分治法求解:归并排序
public:
int ans = 0;
int maxn = 50005;
void merge(vector<int>& nums, int L1, int R1, int L2, int R2){
int i = L1, j = L2;
int temp[maxn], index = 0;
while(i <= R1 && j <= R2){
if(nums[i] <= nums[j]){
temp[index++] = nums[i++];
}
else{
temp[index++] = nums[j++];
//因为左右均为有序递增序列,因此下标为i的元素nums[i]至左序列末尾的元素nums[R1]均能与下标为j的元素nums[j]构成逆序对,所以个数为R1-i+1
ans += R1 + 1 - i;
}
}
while(i <= R1){
temp[index++] = nums[i++];
}
while(j < R2){
temp[index++] = nums[j++];
}
for(i = 0; i < index; ++i){
nums[L1 + i] = temp[i];
}
}
void mergeSort(vector<int>& nums, int left, int right){
if(left < right){
int mid = (left + right) / 2;
mergeSort(nums, left, mid);
mergeSort(nums, mid + 1, right);
merge(nums, left, mid, mid + 1, right);
}
}
int reversePairs(vector<int>& nums) {
int len = nums.size();
mergeSort(nums, 0, len - 1);
return ans;
}
};