您的位置:首页 > 其它

【一个小实验】找出两个数组中相同的元素

2015-08-02 16:31 351 查看
搬运自洒家的QQ空间(不要问我问什么用空间,懒就一个字......),转载请注明出处。

在实际中,我们经常需要找出两个数组A和B中相同的元素(事实上,在面试中或者做题的时候大家也应该遇到过很多这样的题目)。

通常的做法自然是两层for循环,从A中取一个元素α,在B中遍历查找这个α。设A/B的长度分别为N和M。那这个算法的时间复杂度将达到N*M。如果N和M都很大的情况下(比如都是几万),消耗时间通常是我们不能忍受的。

有木有更好的办法也?

恰好这两天在重温《C++ primer》,看到关联容器的时候我就想,有没有可能将其中较小的一个数组(比如B)中的元素全部放进一个HashSet中,然后再遍历另一个数组(A)。通过hash函数来确定是否包含当前数组A中的元素α?

因为,根据Hash函数的特点,只要构造得足够好,那么在Set中查找α的时间复杂度通常是常数级的(甚至是O(1))。

那么整个算法的时间复杂度最好的情况能达到O(N)。

巨大的提升啊~~~~

于是就有了下面这个小实验。

#include <iostream>
#include <vector>
#include <ctime>

using namespace std;

int main()
{
/*
这里我们用两个Vector来模拟两个数组。数组最大长度为N
*/
vector<int> vec;//长的那个
vector<int> vec2;//短的那个,这里被设定只保存偶数,也就是vec长度的一半

//生成测试数据
for (int i = 0; i < 50000; i++)
{
vec.push_back(i);
if (i % 2 == 0)
vec2.push_back(i);
}

clock_t start_time = clock();
{
//被测试代码
cout << "-----------开始测试段 1 " << endl;
//记录下两个VECTOR中重复的数字个数,下同
long counter = 0;
//两个for循环检测
for (int i = 0; i < vec.size(); i++)
for (int j = 0; j < vec2.size(); j++)
{
if (vec2[j] == vec[i])
counter++;
}
cout << "找到重复个数:" << counter << endl;
}
clock_t end_time = clock();

//-------------------------------------
clock_t start_time2 = clock();
{
cout << "------------开始测试段 2 " << endl;
long counter = 0;
//在C++ 11 STL 中,unordered_set就是一个HashSet。因此不需要我们再去手动写一个
unordered_set<int> mSet;
//将较短的vector中的元素复制到Set中去
for (int i = 0; i < vec2.size(); i++)
{
mSet.insert(vec2[i]);
}
//遍历较长的那个数组
for (int i = 0; i < vec.size(); i++)
{
//注意调用set的find方法,这个方法会通过计算Hash值来比较
if (mSet.end() == mSet.find(vec[i]))
counter++;
}
cout << "找到重复个数:" << counter << endl;
}
clock_t end_time2 = clock();
cout << "测试段1耗时: " <<
static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC * 1000 << "ms" << endl;//输出运行时间
cout << "测试段2耗时: " <<
static_cast<double>(end_time2 - start_time2) / CLOCKS_PER_SEC * 1000 << "ms" << endl;//输出运行时间
return 0;
}
实验结果:

当最大长度等于1W的时候():



当最大长度等于5W的时候:



可以看到,通过hashSet来进行查找,耗时仅为两个for循环的数百分之一。超级巨大的性能提升有木有。感觉get到了什么不得了的技能呢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: