一、题目:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:0 <= 数组长度 <= 50000
二、思路和代码:
1、暴力求解:两层循环遍历,找到所有第二层中小于当前元素的所有个数之和。(超时)
public class Solution {
public int reversePairs(int[] nums) {
int cnt = 0;
int len = nums.length;
for (int i = 0; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
if (nums[i] > nums[j]) {
cnt++;
}
}
}
return cnt;
}
}
2、归并排序+统计交换次数。
将数组分割为一个元素的小数组,此时有序,然后两两小数组合并,如果右边的元素有先进临时数组时,说明后面有较小数,计入逆序对数量中。
class Solution {
public:
int mergesort(vector<int>&temp,vector<int>& nums,int l,int r) {
if(l>=r) return 0;
int mid =(l+r)/2;
int count =mergesort(temp,nums,l,mid)+mergesort(temp, nums, mid+1, r);
int i=l,j=mid+1,pos=l;
while(i<=mid && j <= r){
if(nums[i] <= nums[j]){
temp[pos++ ]= nums[i++];
count += j - (mid + 1);
}
else{
temp[pos++] = nums[j++];
}
}
for(int k=i;k<=mid;k++){
temp[pos++]=nums[k];
count +=j - (mid + 1);
}
for(int k=j;k<=r;k++){
temp[pos++]=nums[k];
}
copy(temp.begin()+l, temp.begin()+r+1, nums.begin()+l);
return count;
}
int reversePairs(vector<int>& nums) {
int n=nums.size();
vector<int>temp(n);
return mergesort(temp,nums,0,n-1);
}
};
结果:
怕什么真理无穷,进一步有进一步的欢喜!