题目描述:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对,输入一个数组,求这个数组中的逆序对数。
思路分析:
代码分析:
#include<iostream>
using namespace std;
//********第一种方法:简单粗暴,时间复杂度为O(n2)***********/
int GetRevNum_1(int *arr,int len)
{
if(arr==NULL || len<=0) //判断参数是否合理
{
return 0;
}
int res = 0; //记录逆序对数
for(int i=0;i<len-1;++i) //遍历整个数组
{
for(int j=i+1;j<len;++j) //顺序和它之后的所有数据进行比较
{
if(arr[i] > arr[j])
++res;
}
}
return res;
}
//********第二种方法:经典归并法,时间复杂度为O(nLog2n)***********/
int Item(int *arr,int len,int pos)//分函数,功能是:算出每次归并记录的结果
{
//归并嘛,所以肯定是两队,称之为左对和右队
int res = 0; //记录本次归并逆序对数
int low1 = 0; //左队头
int high1 = pos - 1; //左队尾
int low2 = high1 + 1; //右队头
int high2 = high1 + pos > len-1 ? len-1 : high1 + pos; //右队尾,小心越界
int *brr = new int[len]; //辅助数组,用来存储归并后的数组
int index = high2; //辅助数组的下标
while(low2 < len) //条件成立,则证明左队和右队都存在,可以归并
{
while(low1<=high1 && low2 <= high2)
{
if(arr[high1] > arr[high2]) //证明存在逆序对数
{
res += high2 - low2 + 1; //high2小于high1了,那low2->high2的所有值都小于high1
brr[index--] = arr[high1--]; //把数据存储在辅助空间合适的位置
}else
{
brr[index--] = arr[high2--];
}
}
while(low1<=high1) //左队没走完
{
brr[index--] = arr[high1--];
}
while(low2<=high2) //右队没走完
{
brr[index--] = arr[high2--];
}
//更新左队和右队
low1 = high2 +pos + 1;
high1 = low1 + pos - 1;
low2 = high1 + 1;
high2 = high1 + pos > len-1 ? len-1 : high1 + pos;
index = high2; //更新辅助数组存储下标
}
if(low2 >= len) //可能没构成两组,然后就把剩余的数据赋到辅助数组中去
{
for(int i=low1;i<len;++i)
{
brr[i] = arr[i];
}
}
for(int i=0;i<len;++i) //把辅助数组的值赋给新数组。
{
arr[i] = brr[i];
}
delete[] brr;
return res;
}
int GetRevNum(int *arr,int len)//功能函数:求出总的逆序对数
{
int res = 0; //记录逆序对数
if(arr==NULL || len<=0)//判断参数是否合理
{
return res;
}
for(int i=0;i+2<len;i+=2) //先比较出所有相邻数字之间的逆序对数,相当于第一次归并
{
if(arr[i] > arr[i+1])
{
++res; //逆序对数的值随之增长
int tmp = arr[i]; //并完成交换
arr[i] = arr[i+1];
arr[i+1] = tmp;
}
}
for(int i=2;i<len;i*=2) //开始逐步归并
{
res += Item(arr,len,i);//调用分函数,并且把得到的值进行累计相加
}
return res;
}
int main()
{
int num = 0;
cin>>num;
int *arr = new int[num];
for(int i=0;i<num;++i)
{
cin>>arr[i];
}
cout<<GetRevNum_1(arr,num)<<endl;
cout<<GetRevNum(arr,num)<<endl;
return 0;
}