求交集算法
A. 有什么好的算法求两个数组的交集
首先对较短的一个数组(设长度为a)建立平衡二叉搜索树(需要alog2(a)的时间)。
然后对另一个数组(设长度为b)的每一个元素,在a的搜索树中查找(需要blog2(a)的时间)。
所以总共需要alog2(a)+blog2(a)的时间。
而2楼的算法需要ab的时间。
当b>a>4时,
a>2log2(a)
log2(a)<a-log2(a)
log2(a)/(a-log2(a))<1
alog2(a)/(a-log2(a))<a
又b>a
alog2(a)/(a-log2(a))<b
alog2(a)<ab-blog2(a)
alog2(a)+blog2(a)<ab
所以b>a>4时我的算法比2楼快。
当然,还有常数项的问题,上面的“快”只是渐进意义上的快。
B. 数学求交集
在数轴上把这些不等式表示的范围画出来。画图解很容易的。
注意你可以用不同颜色的笔画。比如-√2<x<√2 用黑笔,x>1或-1 <x<0
用蓝笔,-1<x<1用红笔。最后看图,三种颜色相交的地方(也就是三种颜色的公共地方,三种颜色都有的地方)就是所求的交集。画图时注意实心点和空心的。实心的表示包含这个点,空心表示不含这个点。
注:求并集就是三种颜色所包含的整个范围。
C. 如何计算两个有序整型数组的交集
例如,两个含有n个元素的有序(非降序)整形数组a和b(数组a和b中都没有重复元素),求出其共同元素。
a[]={0,1,2,3,4};
B[]={1,3,5,7,9};
那么它们的交集为{1,3}。
计算数组交集可以采用很多种方法,但数组的相对大小一般会影响算法的效率,所以需要根据两个数组的相对大小来确定采用的方法。
(1)对于两个数组长度相当的情况,一般可以采取以下3种方法。
方法一:采用二路归并来遍历两个数组。(这个名字好霸气,有木有武功招数的赶脚)
设两个数组分别为array1[n1]和array2[n2],分别以i、j从头开始遍历两个数组。在遍历过程中,如果当前遍历位置的array1[i]与array2[j]相等,则此数为两个数组的交集,记录到随便array1或array2中,并继续向后遍历array1和array2.如果array1[i]>array2[j],则需继续向后遍历array2.如果array1[i]小于array2[j],则需要继续向后遍历array1,直到有一个数组结束遍历即停止。总的来说,就是谁落后了,谁的下标就自增去吧。
代码如下:
#include "stdafx.h"
#include <stdio.h>
void mixed(int array1[], int n1, int array2[], int n2)
{
int i = 0, j = 0, k = 0;
while (i < n1&&j < n2)
{
if (array1[i] == array2[j])
{
array1[k] = array1[i];
printf("%d\n", array1[k]);
i++;
j++;
k++;
}
else if (array1[i]>array2[j])
{
j++;
}
else if (array1[i] < array2[j])
{
i++;
}
}
}
void main()
{
int a[] = { 0, 1, 2, 3, 4 };
int b[] = { 1, 3, 5, 7, 9 };
mixed(a, 5, b, 5);
getchar();
}
效果如图:
方法二:顺序遍历两个数组,将数组元素存放到哈希表中,同时对同级的数组元素进行计数。如果为2,则为两者的交集元素。
方法三:遍历两个数组中任意一个数组,将遍历得到的元素存放到哈希表,然后遍历另外一个数组,同时对建立的哈希表进行查询,如果存在,则为交集元素。
(2)对于两个数组长度相差悬殊的情况,如数组a的长度远远大于数组b的长度,则可以采用下面几种方法。
方法一:依次遍历长度小的数组,将遍历得到的数组元素在长数组中进行二分查找。具体而言,设两个指向两个数组为元素的指针,取较小的那个数在另一个数组中二分查找,找到,则存在一个交集,并且将该目标数组的指针指向该位置前一个位置。如果没有找到,同样可以找到一个位置,使得目标数组中在该位置后的数肯定不在另一个数组中存在,直接移动该目标数组的指针指向该位置的前一个位置,再循环找,直到一个数组为空为止。因为两个数组中都可能出现重复的数,因此二分查找时,当找到一个相同的数x时,其下标为i,那么下一个二分查找的下界变为i+1,避免x重复使用。
方法二:采用与方法一类似的方法,但是每次查找在前一次查找的基础上进行,这样可以大大缩小查找表的长度。
方法三:采用与方法二类似的方法,但是遍历长度小的数组的方式有所不同,从数组头部和尾部同时开始遍历,这样可以进一步缩小查找表的长度。
D. 求两个数组的交集算法
数组求交集的方法
1.暴力搜索
2.利用HashMap
3.先排序再用两个指针查找
4.位图法
5.大文件求交集用分治法,组内用位图法
E. C++交集的算法
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<iterator>
#include<set>
#include<algorithm>
using namespace std;
int main(){
srand((unsigned)time(NULL));
int len = 10;
const int limit = 100;
set<int> dSetA;
set<int> dSetB;
vector<int> dVec;
while(len --){
dSetA.insert((int)((double)rand() / RAND_MAX * limit));
dSetB.insert((int)((double)rand() / RAND_MAX * limit));
}
cout << "Set A has " << endl;
(dSetA.begin(), dSetA.end(), ostream_iterator<int>(cout, " "));
cout << endl;
cout << "Set B has " << endl;
(dSetB.begin(), dSetB.end(), ostream_iterator<int>(cout, " "));
cout << endl;
cout << "Set A intersect Set B " << endl;
dVec.clear();
set_intersection(dSetA.begin(), dSetA.end(), dSetB.begin(), dSetB.end(), back_inserter(dVec));
(dVec.begin(), dVec.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
如果你用标准库的话,就这个样子可以了,如果是需要单独的set交集算法
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<iterator>
#include<set>
#include<algorithm>
using namespace std;
void intersection(const set<int>& a, const set<int>& b, vector<int>& out){
typedef set<int>::iterator setIter;
setIter aBegin = a.begin();
setIter aEnd = a.end();
setIter bBegin = b.begin();
setIter bEnd = b.end();
while(aBegin != aEnd && bBegin != bEnd){
if (*aBegin < *bBegin)
++aBegin;
else if(*bBegin < *aBegin)
++bBegin;
else{
out.push_back(*aBegin);
++aBegin;
++bBegin;
}
}
}
int main(){
srand((unsigned)time(NULL));
int len = 10;
const int limit = 100;
set<int> dSetA;
set<int> dSetB;
vector<int> dVec;
while(len --){
dSetA.insert((int)((double)rand() / RAND_MAX * limit));
dSetB.insert((int)((double)rand() / RAND_MAX * limit));
}
cout << "Set A has " << endl;
(dSetA.begin(), dSetA.end(), ostream_iterator<int>(cout, " "));
cout << endl;
cout << "Set B has " << endl;
(dSetB.begin(), dSetB.end(), ostream_iterator<int>(cout, " "));
cout << endl;
cout << "Set A intersect Set B " << endl;
dVec.clear();
intersection(dSetA, dSetB, dVec);
(dVec.begin(), dVec.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
F. python 多个字符串交集算法
如果原数据是唯一的,就把每一个元素,添加到一个字典中
最终获得类似{"A1":5,"A3":2,"D1":5,"D3":10}的字典,也就是记录每一个元素出现的次数,如果是10个元组的交集,那么次数=10。
G. 求C语言描述的,用线性表的,求交集的算法
先排序两个先行表,然后去除重复项。
从一个表(a)第一项开始,为关键字扫描另一个表(b),找一个与其相等的,如果找到,那么在b表之前的项也不会是a表中的项了,然后从a表下一项作关键字,从b表被匹配的元素的下一项开始继续搜索,如果没有找到与a中第一项相等的,到遇到比该项大的项时,便从a中下一项开始,重复以上步骤。
排序就不说了,好多种,冒泡,快排,插入,二分插入都行。去除重复项,可以用以下算法
void StripRepeatElement(int Array[],int Arraylen)
{
int Count = 0;//重复计数器
int i;
for(i = 0;i < ArrayLen;i++)
{
if(Array[i] == Array[i + 1])
{
Count++;
}
else
{
Array[i - Count] = Array[i];
}
}
}
复杂度为O(n)
以下为求交集的算法,假设两个表都已经排过序和剔出重复项了
void GetIntersection(int A[],int Alen,int B[],int Blen)
{
int i = 0,j = 0;
while(i < Alen)
{
while(j < Blen)
{
if(A[i] == B[j])
{
//交集
printf(" %d ",A[i]);
j++;
break;
}
else if(A[i] < B[j])
{
//从A的下一项开始匹配
break;
}
else
{
//比较B的下一项
j++;
}
}
i++;
}
}
复杂度也为O(n)
H. 并集和交集的公式是什么
交集?并集?
你还记得高中数学的第一课吗?讲的是集合,具体定义去网络,里面有两个运算法则:交集和并集。也许你当时觉得很容易,那么今天还是回头想想它在讲什么。
一、两个集合
一切运算都是两个相对的集合间的关系法则,既然是高中数学,那么就略谈一下教育,其实很多人会说“你考好了说明学好了”,然而我想说的是考试和教学是两个集合。
我们看看中国过去的八股文,包括今天的高考,受到那么多诟病,但是为什么还是继续这么做?因为相关部门不知道,无作为?我觉得要是从另外一个角度看,考试作为一种人才选拔的工具,那选拔什么样的人呢?是见多识广、才华横溢的人;还是那些面对一个目标,能持之以恒地找方法达成,坐得住、能下功夫的人呢?
不好意思,答案很可能是后者。
现在很多创业公司都有这样的体会。招人的时候,他们往往不是倾向于招那些有经验的人,而倾向学习能力好、沟通能力强、对自己要求严、有自我驱动能力的人。因为创业公司本来做的就是全新的事情,经验这个东西是有益还是有害,说不清楚。但是面对任何新的情况,都能找到方法、诉诸行动、不丢目标的人,才是创业公司需要的。前一阵还有一位创业公司的创始人跟我说,他发现优秀的大学生,比行业里的老鸟好用。
这种优秀的人,不管面对什么样的题目,哪怕是八股文,也一样可以坐得住、下苦功,最后考出好成绩。这样的人走入仕途,面对自己不熟悉的任务,也一样会表现优秀。事实上,明清两代那么多能人都是靠八股文选拔出来的,比如我们熟悉的王阳明和曾国藩。
再回头来说我们的高考。
这几年,高考的发展趋势和八股文正好相反的,这也是很多人呼吁和推动的结果。各地高考越来越强调地方特色,越来越多地考核学生的所谓“综合素质”。这种发展方向看似正确,但是也有值得反思的地方。
首先,中国是一个大国,各地情况差异巨大,社会阶层也差异巨大。只有坚持全国的统一性,才能确保人才通过高考在全国范围内的流动和交流,维持整个国家的内在联系和国家认同。不夸张地说,如果高考的全国统一性消失了,中国各个地方的内在联系会被严重削弱。
我们不能把高考仅仅看作是教育的一个环节,高考是国家治理中的关键,事关国家的完整统一和治理水平。
其次,虽然不必恢复到八股文那样死板的形式,但高考仍然要尽量维持简单、明晰的考试内容和形式。一言以蔽之,永远要确保,学生只靠几本教科书、只比拼硬功夫、笨功夫就能取得好成绩。
和科举一样,高考不是教育工具,高考是人才选择的工具。它把各个社会阶层里奋发向上,能坐得住、下苦功夫的人挑选出来,保持这个社会的活力和公平。这才是高考在当前中国社会的真实作用。
然而,所谓教育则是一种能力的培养,一种思维模式的锻炼,比如我们讲集合,你不光会做题还要会应用,比如将学习数学思维和考试分开来,当然它们之间有交集,就是你既能坐下来刷题总结,又能进行发散和转化,你要既能学好集合又能考好集合这就是交集,而你只是明白自己要好好学习并且考试优异这就是并集。其实大多数人在看问题的时候喜欢用并集,这样比较省事,也符合原始的认知方式,然而今天这种方式与时代有所不匹配啦,这种人就是那些现在边缘只求安全感,却不愿多向集合内多走一步深入了解的人。我们在许多问题上可以有所区分,比如人工智能就是未来一切的引导?关系问题一定是其中一个人有问题或者两个人有问题?
二、人工智能就是人类的全部模拟?
这个的答案明显是否定的,人工智能是完全通过算法运行的,这些算法都来自于各个学科的模型计算,你去翻翻书,所以学科都有一个所谓的理想假设,这个假设通俗的讲就是,如果世界只有XX学科来指导运行的话。所以人工智能可以模拟任意学科,但是这是不同的集合,交集并不能完全模拟,对于这个问题,很多人认为只要融合了那么交集自然呈现啊,其实不然。举个例子,一些有经验的心理咨询师在处理感情纠葛问题时,会说他面对的是三个人,夫妻双方和他们的关系,而关系就是交集的结果,所以关系问题不一定是个人或者两个人的问题导致,也有可能是他们的交集,也就是产生的关系导致。再者人工智能更偏向科学,而科学思维和技术仅仅是社会中的小部分,还有大部分的人性,也就是社会科学,例如人工智能的围棋站,输的那一局就是输在人性上,所以任何复杂问题回答时,可以考虑下是否存在两个及以上集合,因为可能存在第三者。(上述问题因本文需求,不多做拓展)这样一个是非问题只有两个答案,却可能有三层认知。
三、认知三级跳
最近中子星的新闻应该都看过了,那么问个看问题,宇宙是有限的还是无限的?如果回答宇宙是有限大的,那说明这个人具备了一定的科学素养。如果他回答宇宙是无限大的,那就有两种可能。一种可能是这个人对现代科学一无所知;另一种可能,却是他对天体物理学的最新进展非常了解。
第一层,无限大,从小就知道宇宙浩瀚无边,没有天边,所以无限大。
第二层,有限大,知道宇宙大爆炸,就知道宇宙是个正在被吹大得气球,不管怎么变大,气球总还是有边界的,于是有限大。
第三层,无限大,根据2013最新发现,宇宙质能比例系数为1±0.004,以及宇宙背景辐射的数据,证明在欧几里得空间内,宇宙是一个平面,无限延伸。
那么又会出现一个特别有意思的情况,二八理论,如果去统计下会发现中间层的人会有80%,所以当你和很多别人的观点一样的时候就要警惕啦,你是不是中间层?你也许离出现集合只有一步,而你却沾沾自喜。
同样的事情我们看看对朋友圈的认识,最早用的时候,很多人不习惯的,认为不好所以希望不要有。当发现里面信息多样化,被设计吸引后,几乎大多数人都爱它。而像我自从写出那篇朋友圈是黑暗森林后,至今朋友圈没看过,而我并没有过不下去,或者对我的生活学习工作没有太大影响,那我还去看了干嘛,花去巨大的时间成本,却基本没有收益啊。