剑指 Offer 51. 数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
class Solution { public: //利用递归。 // 将数组分成A[0] ... A[i] ... A[m] A[m+1]....A[j]....A[n]两个数组,利用归并排序递归分治排序两个数组 //逆序对数应该=前一半数组中逆序对数+右一半数组中逆序对+归并两部分数组的逆序对数。 //最主要问题就是,归并两个有序数组过程中的逆序对数怎么算? //例如,A[i]与A[j]合并时,如果 A[i] > A[j],那么A[i+1]...A[m]都是大于A[j]的,就会产生(m-i+1)对 int reversePairs(vector<int>& nums) { int n = nums.size(); if(n == 0 || n ==1) return 0; vector<int> tmp(n,0); int res=0; mergesort(nums,tmp,0,n-1,res); return res; } //merge的过程将left到right有序重新存入nums.归并nums[left,mid],nums[mid+1,right] void merge(vector<int>& nums,vector<int>& tmp,int left,int mid,int right,int& res) { int i=left,j=mid+1,k=left; for(i=left,j=mid+1;i<=mid&&j<=right;){ if(nums[i]<=nums[j]){ tmp[k] = nums[i]; i++; }else{ tmp[k] = nums[j]; j++; res += (mid-i+1); } k++; } //还有未归并完成的 while(i<=mid){ tmp[k]=nums[i]; i++; k++; } while(j<=right){ tmp[k]=nums[j]; j++; k++; } //将tmp重新放入nums,那么nums[left,right]即有序了 for(int i=left;i<=right;i++){ nums[i] = tmp[i]; } return; } //归并排序 void mergesort(vector<int>& nums,vector<int>& tmp,int left,int right,int& res) { if(left < right){ int mid = left+(right-left)/2; mergesort(nums,tmp,left,mid,res); mergesort(nums,tmp,mid+1,right,res); //合并nums[left,mid] nums[mid+1,right] merge(nums,tmp,left,mid,right,res); } return; } };