求逆序数
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。现在,给你一个N个元素的序列,请你判断出它的逆序数是多少。比如 1 3 2 的逆序数就是1。
采用分治法+归并排序的思路:左表初始为[l,m]而右表为[m + 1, r],两个表各有一个指针i和j,因此在任意时刻左表为[i,m]而右表为[j, r]。如果右表为空或者两表都不空且a[i]<=a[j]时,元素i从左表中移出;否则元素j从右表中移出,并累加左表元素个数m --j +1。
void sort (int l , int r)
{
if(l>= r) return 0;
int m=(l+r)>>1;
sort(l, m);
sort(m+1, r);
// merge [l,m] and [m+1,r]
int i=l, j=m+1, c=l;
while (i<=m && j<=r)
if(j> r || ( i<= m && a[i]<=a[j]) )
t[c++] = a[i++];
else
{ t[c++] = a[j++]; cnt += m-i+1; }
// copy back
for(i = l; i<=r; i ++) a[i] = t[i];
}
只要把cnt += m - i + 1;这一句去掉,就是标准的归并排序。时间复杂度也是O(n log n),比普通的O(n^2)算法快很多。需要注意的是附加空间t数组是O(n)的。