该题第一眼看到 就是从头到尾一个一个的比,然后找逆序对。
方法简单,可惜不行。
思考:
我开始分析的思路是 归并吧。
可是 我想到了 把7.5.6,4分成7,5,和6,4这两个数组求逆序对,至于合并这两个含2个元素的数组就找不到好的解决方法。
看了书才明白,需要将合并后的子数组排序,然后分别在两个排序了的子数组中,进行查找,从最后一个最大元素开始,
当前半部分最大的元素 大于后半部的,那么逆序对,加上后半部的元素总数,保存前半部元素,移动指针。
当前半部的最大元素 小于后半部的,那么逆序对 不变,同时保持后半部最大元素,移动指针
现在先来来跑一下归并的code。
归并可以说是稳定的o(nlogn)的算法,为什么呢,因为都是左边比右边,相等的始终在左边。
#include "stdio.h"
#include "string.h"
#define MAX 1024
#define LARGEST 0x7FFFFFFF
void mSort(int *data,int s,int m,int d)
{
int left[MAX],right[MAX];
int i,j,k;
int leftMax,rightMax;
for(i=s;i<=m;i++)
{
left[i-s]=data[i];
}
left[i-s]=LARGEST;
for(j=m+1;j<=d;j++)
{
right[j-m-1]=data[j];
}
right[j-m-1]=LARGEST;
i=0;
j=0;
k=s;
for(k=s;k<=d;k++)
{
if(left[i]<=right[j])
data[k]=left[i++];
else
data[k]=right[j++];
}
}
void mergeSort(int *data,int s,int end)
{
int num=(s+end)/2;
if(s<end)
{
mergeSort(data,s,num);
mergeSort(data,num+1,end);
mSort(data,s,num,end);
}
}
int main()
{
int data[] = {5,3,1,7,8,11,4,6,4,5,4};
int len = sizeof(data)/sizeof(data[0]);
int index=0;
mergeSort(data,0,len-1);
for(index=0;index<len;index++)
printf("%d ",data[index]);
return 0;
}
跑完了归并算法,现在需要想想如何在归并算法中,添加逆序对的计算了。
#include "stdio.h"
#include "string.h"
#define MAX 1024
#define LARGEST 0x7FFFFFFF
int globalReverseNum=0;
void mSort(int *data,int s,int m,int d)
{
int left[MAX],right[MAX];
int i,j,k;
int leftMax,rightMax;
for(i=s;i<=m;i++)
{
left[i-s]=data[i];
}
left[i-s]=LARGEST;
for(j=m+1;j<=d;j++)
{
right[j-m-1]=data[j];
}
right[j-m-1]=LARGEST;
i=m-s;
j=d-m-1;
k=d;
while(k>=s)
{
if(i<0 ||j<0)
break;
if(left[i]>right[j])
{
globalReverseNum+=(j+1);
data[k--]=left[i];
i-=1;
}
else
{
data[k--]=right[j];
j-=1;
}
}
for(;j>=0;j--)
data[k--]=right[j];
for(;i>=0;i--)
data[k--]=left[i];
}
void mergeSort(int *data,int s,int end)
{
int num=(s+end)/2;
if(s<end)
{
mergeSort(data,s,num);
mergeSort(data,num+1,end);
mSort(data,s,num,end);
}
}
int main()
{
int data[] = {5,3,1};
int len = sizeof(data)/sizeof(data[0]);
int index=0;
mergeSort(data,0,len-1);
for(index=0;index<len;index++)
printf("%d ",data[index]);
printf("\n%d\n",globalReverseNum);
return 0;
}