每天学习一算法系列(5)(已知两个数组,数组里的元素有正有负,但是都是按照从小到大已经排好序,要求用尽可能小的时间复杂度编写一算法求出两个数组的最大交集)

来源:互联网 发布:电子地图软件 编辑:程序博客网 时间:2024/05/22 05:33

昨天刚刚去迅雷面试,总体感觉还不错,不过有的填空题目做错的太冤枉了,也都怪平时养成马虎的习惯,以后一定要改掉这样的毛病,总体来说题目质量还是不错的,有选择题,填空题,简答题,算法题,主要考C++对象模型的知识比较多,还零星的考一些COM相关题目,至于算法题还蛮简单的,有两道,第一道是反转链表,另外一道就是我这篇文章所要讲的题目。

 

题目:已知两个数组,数组里的元素有正有负,但是都是按照从小到大已经排好序,要求用尽可能小的时间复杂度编写一算法求出两个数组的最大交集。如:

A[] = {-10,5, 6},

B[] = {2, 4, 5, 6, 12};

那么交集为: {5, 6}

 

 

思路一:

顺序取出数组A中的每个元素,然后对取出的每个元素在数组B中进行二分查找,如果没有找到,一直到结束,如果找到,假如找到的元素在B中的Index为J,在A中的Index为I,那么从I+1,J+1开始对两个数组进行取元素并进行比较,如果相等则一直继续,如果不相等,那么从Index I到当前Index-1就是两个数组的最大交集.

 

代码如下:

/*---------------------------------Copyright by yuucyf. 2011.04.26求两数组的最大交集----------------------------------*/#include "stdafx.h"#include <assert.h>int FindValue(const int *pB, int i32FirIdx, int i32EndIdx, int nValue){assert(NULL != pB);if (i32FirIdx > i32EndIdx)return -1;int i32MidIdx = (i32FirIdx + i32EndIdx) / 2;if (pB[i32MidIdx] > nValue){return FindValue(pB, i32FirIdx, i32MidIdx - 1, nValue);}else if (pB[i32MidIdx] < nValue){return FindValue(pB, i32MidIdx + 1, i32EndIdx, nValue);}return i32MidIdx;}bool GetMaxSubArray(const int *pA, int nASize, const int *pB, int nBSize){assert(NULL != pA || NULL != pB);assert(0 <= nASize || 0 <= nBSize);int i32Idx = -1;int i32I = 0, i32J = 0;for (i32I = 0; i32I < nASize; i32I++){if ((i32Idx = FindValue(pB, 0, nBSize - 1, pA[i32I])) != -1){printf("Max sub array is : %d ", pA[i32I]);for (i32I++, i32J = i32Idx + 1; i32I < nASize && i32J < nBSize; i32I++, i32J++){if (pA[i32I] == pB[i32J]){printf("%d ", pA[i32I]);}}return true;}}return false;}int _tmain(int argc, _TCHAR* argv[]){int aryA[] = {-10, 5, 6};int aryB[] = {2, 4, 5, 6, 12};if (!GetMaxSubArray(aryA, sizeof(aryA)/sizeof(int), aryB, sizeof(aryB)/sizeof(int))){printf("Not sub array!\n");}return 0;}


 

 

时间复杂度为O(n * logn)

 

思路二:
    直接借用stl中的Map来求去交集,集体想法是:先把数组A中的元素插入到map中,把值当作Key, Value设置为1,然后用数组B中的元素作为Key去查询map,如果找到,并且值为1那就说明存在交集, 然后接着数组B的下个元素往下继续查找,如果没有找到,那么就记录下改交集的长度,然后依次往下查找,记录所有的交集,最后遍历完后,比较所有的交集找出最大的交集即可.