现在的位置: 首页 > 综合 > 正文

面试题:关于两个大数组数据排异的问题

2013年01月29日 ⁄ 综合 ⁄ 共 2120字 ⁄ 字号 评论关闭

记不得什么时候,我们群里发问题,如下:

有两个表,各存放了数亿条网址记录,而这两个表中有一部分是相同的,现在求出两个表中不同的数据项。

咋一看这题目,我就没辙了,如果简单用sql语句,恐怕不知道要何时才能得出结果,所以需要将他们取出来放到数组中。而如果把他们从数据库中取出来,又有什么办法能够求出呢?假设那两个数组分别为A []、B[],如果我首先遍历数组A,然后每条数据都遍历数组B,那效率也是相当的慢。

前思后想,忽然有个思路,倒是可以跟大家交流一下。

步骤1)首先对两个数组排序。对于排序我们都知道有多种方法,我们就用最快的排序,快速排序对它们排序吧。

假如数组A的数据如下:

[0] www.blog.com

[1] www.amazon.com

[2] www.sina.com

[3] www.baidu.com

[4] www.sohu.com

 

数组B的数据如下:

[0] www.blog.com

[1] www.sina.com

[2] www.iteye.com

[3] www.csdn.com

[4] www.sohu.com

 

排序的时候,前边的字符串www.可以直接抛弃不管,只对www.字符串之后的数据排序,排序的时候要注意了,不能仅仅对第一个字符进行排序,还要对字符以后的数据依次排序。如对数组A的排序,排序后结果如下:

[0] www.amazon.com

[1] www.blog.com

[2] www.baidu.com

[3] www.sina.com

[4] www.sohu.com

此时我们已经对首字母进行排序了,然而我们还需要对首字母后的数据依次排序,结果如下:

[0] www.amazon.com

[1] www.baidu.com

[2] www.blog,com

[3] www.sina.com

[4] www.sohu.com

 

注意粗斜体部分,他们的位置已经发生了变化。当然首字母以后的字母排序和首字母排序可以写到一起,我是为了说明问题,并不说要排序两次。

 

数组B的排序如数组A,排序后结果如下:

[0] www.blog.com

[1] www.csdn.com

[2] www.iteye.com

[3] www.sina.com

[4] www.sohu.com

 

排序完成了,进行步骤2.

 

步骤2)

同时对两个数组循环比较。

1)两个数组的长度不一定是相等的,所以要求出两个数组的长度,取最大长度。

代码大致如此: long count = length(A) > length(B) ? length(A) : length(B);

2)然后来个循环,根据下标依次比较两个数组,如果数组A[i]的首字目比B[i]的小,那么A[i]为异同项,那么数组A的下标则向下移一位,然后继续与B[i]比较,直到B[i]的项比它小为止;如果数组A[i]的首字目比B[i]的大,则B[i]为异同项,则数组B的下标下移一位,继续与A[i]项比较,直到B[i]比它大为止;如果相等,那么他们的下标都下移一位。比较时必要时还要比较首字母后续部分。循环次数为count;

以以上的数据举例:

先用A[0]与B[0]比较,则发现A[0] www.amazon.com比B[0]
www.blog.com
的首字母小,那么A[0]  www.amazon.com则是异同项,那么A[0]的数组下标下移一位即:www.baidu.com,继续与B[0]www.blog.com比较;

此时将发现它们首字母相同,那么继续对第二个字符比较,很快发现 A[1] www.baidu.com比B[0]www.blog.com小,那么A[1]也是异同项;

继续对A的数组下移一位 A[2]对 B[0]进行比较,那么发现他们是相同的,此时将他们所有的下标都下移一位,用A[3]对B[1]进行比较,按照上边的发法,那么发现,A[3]比B[1]、B[2]都大,所以B[1]、B[2]都是异同项;

而对A[3]与B[3]比较时,发现他们是相同项,所以他们的数组下标都下移一位;

用A[4]与B[4]进行比较时,发现他们是相同项,所以他们的下标也下移一位;

此时循环条件已经不满足了,所以他们退出循环;

 

由此可以知道,他们的异同项为:A[0] www.amazon.com、 A[1]
www.baidu.com
、B[1]www.csdn.com、B[2] www.iteye.com

此时求解完毕。如果快速排序的情况最坏为 n*n,那么我们的运行次数为:

数组A的排序:length(A)*length(A)

加上数组B的排序length(B)*length(B)

再加上比较的次数count,那么总数为:length(A)*length(A) +length(B)*length(B) + length(A) > length(B) ? length(A) : length(B);这好像比我刚开始说的循环遍历数组A,每一项再遍历数组B依次比较公用的时间length(A)*length(B)的时间要多出很多。然而大家都知道,快速排序的这种情况基本上很少出现,平均情况下只需要:n(log n),也就是说比如数组A、B各有1亿条数据,每个只需要循环8亿次,一共加起来共计算18亿次,这明显比每项依次比较1亿*1亿要好很多。

 

 

抱歉!评论已关闭.