题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
思路:
- 第一种思路即是最普通的方式,从头到尾挨个遍历数组,没遍历到一个元素,再挨个遍历该元素后面的所有元素,将比该元素小的所有元素的所有情况计数。
- 归并排序的方法,这种思路先把数组分割一分为2,如果能再分割的话,继续把两个子数组一分为2,知道后面的子数组为两个元素或者一个元素,即不能分割为止,分割步骤完成,后面就要进行从小到大排序了,以下面的例子来说,到了箭头说明排序这一步,就要开始计算逆序对的数目,就在把两个子数组中的数据组合成一个升序数组的过程中当前面数组的对应的元素大于后面数组的元素时,那么就把其中大的元素置为升序数组中的一个元素,并且后面数组中包括该元素本身前的所有元素肯定也都小于前面数组中的该元素,因为前后两个数组也都是升序的,确定好升序数组中一个元素后,把元素大的数组中中的指针位置往前移动一个,说的有点绕,看下面第二张图就清楚了。
代码:
class solultion
{
public:
int GetNumbers(vector<int> &data,int begin ,int end)
{
/*递归结束条件*/
if(begin==end)
return 0;
int mid=(begin+end)/2;
int LeftNumbers=GetNumbers(data,begin,mid);
int RightNumbers=GetNumbers(data,mid+1,end);
int tempData[end-begin+1];
int Numbers=0;
int LeftIndex=mid,RightIndex=end,tempIndex=end;
while(LeftIndex>=begin&&RightIndex>=mid+1)
{
/*当左边子数组的索引元素大于右边子数组索引元素值*/
if(data[LeftIndex]>data[RightIndex])
{
tempData[tempIndex]=data[LeftIndex];
tempIndex--;
LeftIndex--;
/*当确定一个元素时,右数组该索引位置左边所有元素一定小于左边子数组该元素*/
Numbers+=RightIndex-mid;
}
else
{
tempData[tempIndex]=data[RightIndex];
tempIndex--;
RightIndex--;
//Numbers++;
}
}
if(LeftIndex!=0)
{
while(LeftIndex)
{
tempData[tempIndex]=data[LeftIndex];
LeftIndex--;
tempIndex--;
}
}
if(RightIndex!=0)
{
while(RightIndex)
{
tempData[tempIndex]=data[RightIndex];
RightIndex--;
tempIndex--;
}
}
for(int i=begin;i<end;i++)
{
data[i]=tempData[i];
}
return LeftNumbers+RightNumbers+Numbers;
}
}