今天听同学说做了某顶尖公司笔试,有一题是求逆序对的个数
所谓逆序对,就是在数组中符合 A[i]>A[j] 且 i< j 条件的一对数
比如 数组 {3,1,0,2} 中 存在{3,1} {3,0} {3,2} {1,0} 四组逆序对
一看到这种题目,首先能想到的是暴力解法,注意匹配,但这种解法应该也拿不到这个公司offer,但有方法总比没方法强。
回大学城孤岛的地铁上百度了下,经典题目啊,可以用归并排序的思想来解决,回来就写了
在写下面这份代码的时候比较仓促,比较乱,不过一时兴起写的,将就下吧,写完还改了几下才测试成功
没有百度逆序对的英文,用了难以接受的拼音,先将就下吧,英文不好
思路
归并首先分治
数组变为
3,1 | 0,2
3,1 有一对逆序对 0,2 没有
进入下一轮,此时数组变为 1,3 | 0,2
此时有 1,0 3,0 3,2 3对逆序对
归并1时 另一指针在0 归并3时 另一指针在2 对应逆序对的数量为坐标差+1
/*************************************************************************
> File Name: nixudui.cpp
> Author: chunquanL
> Created Time: 2017-04-03
************************************************************************/
#include<iostream>
using namespace std;
int merge(int data[],int copy[],int start,int mid,int end,int *count)
{
int bmid = mid;
int bstart = start;
int cnt = start;
while(start<bmid && mid<=end)
{
if(data[start]>data[mid])
{
*count += mid-bmid+1;
copy[cnt++] = data[mid++];
}
else
copy[cnt++] = data[start++];
}
if(bmid>start)
*count += (bmid-1-start)*(end-bmid+1);
while(start<bmid)
{
copy[cnt++] = data[start++];
}
while(mid<=end)
{
copy[cnt++] = data[mid++];
}
for(int i=bstart;i<=end;i++)
data[i] = copy[i];
return *count;
}
int get_num_of_nixudui_core(int data[],int copy[],int start,int end,int *count)
{
if(start>=end)
return 0;
int mid = start+(end-start)/2;
if(mid>start)
get_num_of_nixudui_core(data,copy,start,mid,count);
if(end>mid+1)
get_num_of_nixudui_core(data,copy,mid+1,end,count);
return merge(data,copy,start,mid+1,end,count);
}
int get_num_of_nixudui(int data[],int len)
{
if(data==NULL || len<1)
return 0;
int count=0;
int *copy = new int[len];
get_num_of_nixudui_core(data,copy,0,len-1,&count);
delete[] copy;
return count;
}
int main(void)
{
int data[] = {3,5,1,0,2};
int len = sizeof(data)/sizeof(data[0]);
for(int i=0;i<len;i++)
cout<<data[i];
cout<<endl;
cout<<get_num_of_nixudui(data,len)<<endl;
for(int i=0;i<len;i++)
cout<<data[i];
return 0;
}
目前进行的测试都通过了,我觉得是没问题的,出问题了还敬请斧正。