每天学习一算法系列(5)(已知两个数组,数组里的元素有正有负,但是都是按照从小到大已经排好序,要求用尽可能小的时间复杂度编写一算法求出两个数组的最大交集)
2011-04-26 18:11
671 查看
昨天刚刚去迅雷面试,总体感觉还不错,不过有的填空题目做错的太冤枉了,也都怪平时养成马虎的习惯,以后一定要改掉这样的毛病,总体来说题目质量还是不错的,有选择题,填空题,简答题,算法题,主要考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就是两个数组的最大交集.
代码如下:
时间复杂度为O(n * logn)
思路二:
直接借用stl中的Map来求去交集,集体想法是:先把数组A中的元素插入到map中,把值当作Key, Value设置为1,然后用数组B中的元素作为Key去查询map,如果找到,并且值为1那就说明存在交集, 然后接着数组B的下个元素往下继续查找,如果没有找到,那么就记录下改交集的长度,然后依次往下查找,记录所有的交集,最后遍历完后,比较所有的交集找出最大的交集即可.
题目:已知两个数组,数组里的元素有正有负,但是都是按照从小到大已经排好序,要求用尽可能小的时间复杂度编写一算法求出两个数组的最大交集。如:
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的下个元素往下继续查找,如果没有找到,那么就记录下改交集的长度,然后依次往下查找,记录所有的交集,最后遍历完后,比较所有的交集找出最大的交集即可.
相关文章推荐
- 每天学习一算法系列(5)(已知两个数组,数组里的元素有正有负,但是都是按照从小到大已经排好序,要求用尽可能小的时间复杂度编写一算法求出两个数组的最大交集)
- 每天学习一算法系列(3)(设计包含min函数的栈,要求函数min、push以及pop的时间复杂度都是O(1))
- 每天学习一算法系列(3)--设计包含min函数的栈,要求函数min、push以及pop的时间复杂度都是O(1))
- 每天学习一算法系列(29)(有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b 中的元素,使[序列a 元素的和]与[序列b 元素的和]之间的差最小)
- 算法面试题——两个有序数组,将一个数组放入另一个空间很大的数组,要求合并之后依然有序,时间复杂度要求最小,不使用额外的数组。
- 有一堆扑克牌,其中某张牌的张数超过了扑克牌总数的一半,请找到这张牌。写出算法思路、代码实现和算法的时间复杂度,要求算法尽可能高效。假设给定一个扑克牌的数组poker和它的大小n,请返回所求的扑克牌。
- 数据结构和算法学习系列之最大子序列求和问题的O(N)时间复杂度
- 已知m和n是已经排序好的数组,从小到大,现在要合并这两个数组内的数到一个数组,仍然要求是从小到大排序
- 每天学习一算法系列(34)(求一个二叉树中任意两个节点间的最大距离,两个节点的距离的定义是这两个节点间边的个数)
- 找出具有n个元素的集合中最大的两个元素,要求比较次数尽可能少(三种算法的思考)
- 每天学习一算法系列(32)(求一个矩阵中最大的二维矩阵(元素和最大))
- 给一个数组[a1,a2,a3....an],要求出令ai-aj有最大值,其中i<=j,时间和空间复杂度尽可能小
- 每天学习一算法系列(14) (输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字)
- 已知m和n是已经排序好的数组,从小到大,现在要合并这两个数组内的数到一个数组,仍然要求是从小到大排序
- 已知m和n是已经排序好的数组,从小到大,现在要合并这两个数组内的数到一个数组,仍然要求是从小到大排序
- 试设计一个算法,将数组A(0..n-1)中的元素循环右移k位,并要求空间复杂度为O(1),时间复杂度为O(n)。
- 编写一个PHP函数。求任意n个正负整数里面最大的连续和,要求算法时间复杂度尽可能低
- 长度为n的整数数组,找出其中任意(n-1)个乘积最大的那一组,只能用乘法,不可 以用除法。要求对算法的时间复杂度和空间复杂度作出分析,可以写思路也可以写程序。
- 编写一个PHP函数。求任意n个正负整数里面最大的连续和,要求算法时间复杂度尽可能低。
- 已知一个整数数组A[n],写出算法实现将奇数元素放在数组的左边,将偶数放在数组的右边。要求时间复杂度为O(n)。