我的原始想法是创建一个A集合的哈希表,并在其中搜索B集合中的每个元素。然而,我不知道有什么方法可以创建一个数据集的哈希表,它的范围只需要O(n)的空间。我应该考虑完全不同的方法吗?
更新: 我联系了教授关于这个问题,询问如何实现哈希表,他的回答是: 请注意,哈希操作仅在平均情况下需要O(1)时间。我们需要一个最坏情况下的O(n)时间算法来解决这个问题。
因此,看起来这个问题正在寻找一种不同的方法...
输入:数组A[m],B[n]
输出:如果它们不相交,则为True,否则为False
1. 暴力方法:时间复杂度O(m*n),空间复杂度O(1)
1. Search for each element of A into B
2. As soon as you get a match break and return false
3. If you reach till end, return true
优点:不修改输入内容
2. 同时排序 O(mlogm + nlogn + m + n)
1. Sort both arrays
2. Scan linearly
缺点:修改了输入内容。
3. 小数组排序 O((m + n)logm)
1. Say, m < n, sort A
2. Binary search for each element of B into A
缺点:会修改输入
4. 较大的排序 O((m + n)logn)
1. Say n > m, sort B
2. Binary search for each element of A into B
缺点:修改了输入内容
5.哈希 O(m + n)时间复杂度,O(m) 或 O(n)空间复杂度
优点:不会修改输入内容
为什么不使用哈希表呢?如果它们都是唯一的,创建哈希表的时间复杂度为O(n),搜索的时间复杂度也为O(n),总时间复杂度为O(2n) = O(n),这不是很高效吗?
哈希集合将适用。即使这并不严格正确,但认为哈希集/表每个操作是常数时间的做法非常普遍。
请注意,哈希集合/表绝对只使用与插入元素成比例的空间,而不是潜在的总元素数。您似乎误解了这一点。
如果“通常被认为足够好”在某些原因下不可接受,则可以使用基数排序。它是输入元素的总表示大小的线性时间。(注意:这与元素数量的线性时间略有不同。)
#include <bits/stdc++.h>
using namespace std;
int main()
{
unordered_map<string,int>m;
int n,i;
cin>>n;
string a,b; // for storing numbers upto n^100
for(i=0;i<n;i++)
{
cin>>a;
m[a]=1;
}
for(i=0;i<n;i++)
{
cin>>b;
if(m[b])
{
cout<<"Not disjoint";
exit(0);
}
}
cout<<"Disjoint";
return 0;
}
时间复杂度:O(n) 辅助空间:O(n)
你可以使用基数排序算法,以n为基数对输入进行排序。
这将需要101次迭代遍历每个数组(因为输入数字的范围在0到n^100之间)。
一旦你排好了输入,你可以用O(n)的时间按照显而易见的方式进行比较。
注意:为了使基数排序在O(n)的时间内运行,你需要检查从输入数字中提取第k位(基数为n)是否是O(1)的。你可以通过(k-1)次除以n和一次模运算来实现。由于k最多为101,所以这是O(1)的。
旁注 我注意到kennytm@在2010年也给出了类似的答案,但由于评论者指出“基数排序的时间复杂度为O(nk),其中n是键数,k是平均键长度。由于最大键值为n ^ 100,所以最大键长度将是100 log n。因此,这仍然是O(n log n),与所有最佳排序算法相同。”答案被删除。
请注意,该评论是错误的--最大键长为101,因为键是一系列数字的某个基数,并且不能用比特来衡量。
n
在这个问题中的含义,以及在复杂性分析中通常表示什么(输入的位数)。 - Steve Jessop