A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效
来源:互联网 发布:二手交易管理系统源码 编辑:程序博客网 时间:2024/06/06 00:41
思路1:排序法
对集合A和集合B进行排序(升序,用快排,平均复杂度O(N*logN)),设置两个指针p和q,同时指向集合A和集合B的最小值,不相等的话移动*p和*q中较小值的指针,相等的话同时移动指针p和q,并且记下相等的数字,为交集的元素之一,依次操作,直到其中一个集合没有元素可比较为止。
优点:操作简单,容易实现。
缺点:使用的排序算法不当,会耗费大量的时间,比如对排好序的集合使用快排, 时间复杂度是O(N2)
这种算法是大家都能比较快速想到的办法,绝大多数时间放在了对集合的排序上,快排的平均复杂度是O(N*logN),对排好序的集合做查找操作,时间复杂度为O(N),当然这种算法肯定比遍历要快多了。
#include <stdio.h> #include <stdlib.h> #define M 8 #define N 5 int cmp(const void *a, const void *b) { int *x = (int *)a; int *y = (int *)b; return (*x) - (*y); } int main(void) { int A[] = {-1, 2 ,39 ,10, 6, 11, 188, 10}; int B[] = {39 ,8 , 10, 6, -1}; //对数组A和数组B进行快排 qsort(A, M, sizeof(int), cmp); qsort(B, N, sizeof(int), cmp); //FindIntersection(A, B); int i = 0, j = 0; int cnt = 0; int result[M > N ? M : N];//保存集合的结果 //设置i、j索引,分别指向数组A和B,相等则同时移动,不相等则移动较小值的索引 while(i < M && j < N) { if(A[i] == B[j]) { result[cnt] = A[i]; i++; j++; cnt++; } else if(A[i] < B[j]) { i++; } else { j++; } } for(i = 0; i < cnt; i++) { printf("%4d", result[i]); } return 0; }
思路2:索引法
以空间换时间,把集合(集合里面的元素是不重复的!)中的元素作为数组下表的索引。来看例子:
A= {1 ,12, 13, 25},那Asub[1] = 3,Asub[12] = 1 ,Asub[13] = 1 ,Asub[25] = 1 ;
B={1, 2, 3, 15 ,}那Bsub[1] = 1; Bsub[2] = 1; Bsub[3] = 1; Bsub[15] = 1;
对元素少的集合扫一遍,发现Asub[1] = 3 和Bsub[1] = 1有相同的索引1,并且重复度为1,所以交集肯定包括{1, 1}; Bsub[2] = 1而Asub[2] = 0,表示无交集,依次类推,可以得到集合A和B的交集。
假设集合中存在负数,可以把集合分成正整数和负整数(加个负号变正整数)两部分,解法同上!
优点:速度快,时间复杂度O(N)
缺点:空间消耗大,以空间换取时间
这是我看到题目第一个想到的算法,再来想到排序法,而集合压缩是有感而发的,索引法的缺点是空间消耗多,
原因是可能索引值太大,要申请很多的不必要的空间,这个缺点也是有克服的方法的,就是采用哈希查找,找到一个
比较合适的哈希函数,把索引的值减小了,从而减少消耗的内存空间。
比如哈希函数为f(x) = (x + MOD) % MOD (除留余数法,MOD为常数),还有平方取中法、折叠法等方法,然
而,无论哈希函数设计有多么精细,都会产生冲突现象,也就是2个关键字处理函数的结果映射在了同一位置上,因
此,有一些方法可以避免冲突。这里没有仔细钻研,只提供一些思路,有兴趣的朋友可以继续研究。
code:(代码仅适用与正整数部分,未处理负数)
/* Tencent: A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define M 6 #define N 5 int Mymin(int a, int b) { return a < b ? a : b; } int main(void) { int A[] = {1, 10, 12, 23, 5, 45}; int B[] = {1, 10, 12, 123, 52}; //find MaxNumber in A int ifindA = 0; int MaxInA = A[0]; for(ifindA = 0; ifindA < M; ifindA++) { MaxInA = MaxInA > A[ifindA] ? MaxInA : A[ifindA]; } //find MaxNumber in B int ifindB = 0; int MaxInB = 0; for(ifindB = 0; ifindB < M; ifindB++) { MaxInB = MaxInB > A[ifindB] ? MaxInB : A[ifindB]; } int *AsubPositive = (int *)malloc(sizeof(int) * (MaxInA + 1)); int *BsubPositive = (int *)malloc(sizeof(int) * (MaxInB + 1)); memset(AsubPositive, 0, sizeof(int) * (MaxInA + 1)); memset(BsubPositive, 0, sizeof(int) * (MaxInB + 1)); //COPY Positive and Negative numbers of A int i = 0; for(i = 0; i < M; i++) { AsubPositive[A[i]]++; } //COPY Positive and Negative numbers of B int j = 0; for(j = 0; j < N; j++) { BsubPositive[B[j]]++; } int k = 0; int icount = 0; //扫描AsubNegative和BsubPositive printf("the Intersection of A and B is : { "); for(k = 0; k < M; k++) { //有交集输出该数 icount = Mymin(AsubPositive[A[k]], BsubPositive[A[k]]); if(icount == 1) { printf("%-3d",A[k]); } A[k] = 0; } printf(" }"); return 0; }
- A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效
- A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效
- A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效
- A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效。
- A,B两个整数集合,设计一个算法求他们的交集,尽可能的高效
- A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效
- A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效。
- A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效。
- A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效。
- A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效
- A,B两个整数集合,设计一个算法求他们的交集,尽可能的高效(牛客网)
- A、B两个整数集合,设计一个算法求他们的交集
- A,B两个整数集合,设计一个算法求他们的交集
- A、B两个整数集合的交集
- 有两个有序整数集合a和b,写一个函数找出它们的交集
- 有两个有序整数集合a和b,写一个函数找出它们的交集?
- 两个整数集合A,B,求二者交集、并集、差集
- 求两个集合的交集
- ypedef struct LNode结构指针
- apache Mina自学
- java初级之24方法的重载
- 基于Tair存储的广告服务性能优化总结及思考
- 寻址范围总结
- A、B两个整数集合,设计一个算法求他们的交集,尽可能的高效
- git reset应用场景说明
- Linux开放1521端口允许网络连接Oracle Listene
- ScrollView,使用v4包下进行和新控件使用
- virtualenv命令行创建django项目
- 跑马灯状态获取(停止后自动隐藏,用于广告推送等)
- 欢迎使用CSDN-markdown编辑器
- 在Linux操作系统上使用光盘搭建yum源
- 五分钟利用docker搭建好php7.0.10+nginx服务环境