创新工场笔试题:
给定一整型数组,若数组中某个下标值大的元素值小于某个下标值比它小的元素值,称这是一个反序。
即:数组a[]; 对于i < j 且 a[i] > a[j],则称这是一个反序。
给定一个数组,要求写一个函数,计算出这个数组里所有反序的个数。
创新工场的这道求反序个数的题就是算法导论中的题目。其实是对归并排序做些修改,算法的复杂度是nlgn。
程序代码如下:
//算法思想:并归排序数组S
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <malloc.h>
#include <ctime>
int merge(int *a, int low, int mid, int high);
int mergesort(int *a, int low, int high);
int main()
{
int i,k,length;
srand((unsigned)time(NULL));
length=rand()%20;//随即产生数组长度
int *arry=new int[length];
for (i=0;i<length;i++)
{
arry[i]=rand()%100;//产生伪随机数
}
cout<<"数组归并排序前: "; //输出初始关键字序列
for (k=0;k<length;k++)
cout<<arry[k]<<" ";
cout<<endl;
int count=mergesort(arry,0,length-1);//归并排序返回逆数对
cout<<"数组归并排序后: "; //输出初始关键字序列
for (k=0;k<length;k++)
cout<<arry[k]<<" ";
cout<<"\n逆序对为:"<<count<<endl;
getchar();
return 0;
}
int merge(int *a, int low, int mid, int high)
{
int n1 = mid-low+1;
int n2 = high-mid;
int *tmp1 =(int*)malloc(n1*sizeof(int));
int *tmp2 = (int*)malloc(n2*sizeof(int));
int i, j, k;
for(i=0; i<n1; i++)
{
tmp1[i] = a[low+i];
}
for(i=0; i<n2; i++)
{
tmp2[i] = a[mid+i+1];
}
int count=0;
k = low;
for(i=0, j=0; i<n1 && j<n2;)
{
if(tmp1[i]<=tmp2[j])
{
a[k++] = tmp1[i++];
}
else
{
a[k++] = tmp2[j++];
count+=(n1-i);//计算逆数对
}
}
while(i<n1)
{
a[k++] = tmp1[i++];
}
while(j<n2)
{
a[k++] = tmp2[j++];
}
free(tmp1);
free(tmp2);
return count;
}
int mergesort(int *a, int low, int high)
{
int count=0;
if(low < high)
{
int mid = (low+high)/2;
count+=mergesort(a, low, mid);
count+=mergesort(a, mid+1, high);
count+=merge(a, low, mid, high);
}
return count;
}