题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
剑指offer解法,还未理解
public class Solution {
public int InversePairs(int [] array) {
if(array==null||array.length==0) return 0;
int[] copy=new int[array.length];
for(int i=0;i<copy.length;i++){
copy[i]=array[i];
}
return InversePairsNum(array,copy,0,copy.length-1);
}
int InversePairsNum(int[] array,int []copy,int start,int end){
if(start==end){
copy[start]=array[start];
return 0;
}
int length=(end-start)/2;
int left=InversePairsNum(copy,array,start,start+length);
int right=InversePairsNum(copy,array,start+length+1,end);
int pos=end;
int i=start+length;
int j=end;
int count=0;
while(i>=start&&j>=start+length+1){
if(array[i]>array[j]){
copy[pos--]=array[i--];
count+=j-start-length;
}else{
copy[pos--]=array[j--];
}
}
while(i>=start){
copy[pos--]=array[i--];
}
while(j>=start+length+1){
copy[pos--]=array[j--];
}
return left+right+count;
}
}
另一种解法,容易理解
class Solution {
public:
int InversePairs(vector<int> data) {
int length = data.size();
return mergeSort(data, 0, length-1);
}
int mergeSort(vector<int>& data, int start, int end) {
// 递归终止条件
if(start >= end) {
return 0;
}
// 递归
int mid = (start + end) / 2;
int leftCounts = mergeSort(data, start, mid);
int rightCounts = mergeSort(data, mid+1, end);
// 归并排序,并计算本次逆序对数
vector<int> copy(data); // 数组副本,用于归并排序
int foreIdx = mid; // 前半部分的指标
int backIdx = end; // 后半部分的指标
int counts = 0; // 记录本次逆序对数
int idxCopy = end; // 辅助数组的下标
while(foreIdx>=start && backIdx >= mid+1) {
if(data[foreIdx] > data[backIdx]) {
copy[idxCopy--] = data[foreIdx--];
counts += backIdx - mid;
} else {
copy[idxCopy--] = data[backIdx--];
}
}
while(foreIdx >= start) {
copy[idxCopy--] = data[foreIdx--];
}
while(backIdx >= mid+1) {
copy[idxCopy--] = data[backIdx--];
}
for(int i=start; i<=end; i++) {
data[i] = copy[i];
}
return (leftCounts+rightCounts+counts);
}
};