1. 題目
在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數。
示例 1:
輸入: [7,5,6,4]
輸出: 5
限制:
0 <= 數組長度 <= 50000
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
2. 歸併排序
-
方法1:後半部出隊寫入臨時數組時,sum + 前半部 沒有出來的個數(比後部出隊的那個大)
-
方法2:前半部出隊,sum+ 後半部 已經出隊的數量(比出隊的那個小),有後續操作,當後半部全部出隊了完畢,前半部繼續出隊,整個後半部分都比剩餘的前半部分小。
兩種方法只能取其一。
class Solution {
int sum = 0;
vector<int> temp;
public:
int reversePairs(vector<int>& nums) {
temp.resize(nums.size());
mergesort(nums,0,nums.size()-1);
return sum;
}
void mergesort(vector<int>& arr, int l ,int r)
{
if(l >= r)
return;
int mid = l + ((r-l)>>1);
mergesort(arr,l,mid);
mergesort(arr,mid+1,r);
merge(arr,l,mid,r);
}
void merge(vector<int>& arr, int l, int mid, int r)
{
int i = l, j = mid+1, k = 0;
// 方法1:後半部出隊,sum+前半部 沒有出來的個數(比後面大的)
while(i <= mid && j <= r)
{
if(arr[i] <= arr[j])
temp[k++] = arr[i++];
else
{
temp[k++] = arr[j++];
sum += mid-i+1;
}
}
while(i <= mid)//後面都出完了,前半部還剩一些
temp[k++] = arr[i++];
while(j <= r)
temp[k++] = arr[j++];
for(i = l,j = 0; j < k; )
arr[i++] = temp[j++];
//---------------------------------------------------
//方法2:前半部出隊,sum+ 後半部 已經出隊的數量(比前面的小)
while(i <= mid && j <= r)
{
if(arr[i] <= arr[j])
{
temp[k++] = arr[i++];
sum += j-(mid+1);
}
else
temp[k++] = arr[j++];
}
while(i <= mid)//後面都出完了,前半部還剩一些,還需要操作
{
temp[k++] = arr[i++];
sum += j-(mid+1);
}
while(j <= r)
temp[k++] = arr[j++];
for(i = l, j = 0; j < k; )
arr[i++] = temp[j++];
}
};