假设A和B是两个大小相同但每个都没有重复成员的数组。
是否有任何有效的算法?1.确定A和B是否具有相同的成员
2.如果1的答案为真,则决定将A带到B的排列的符号(f(A [i])== f(B [i]))?
谢谢。
答案 0 :(得分:2)
您可以使用哈希表找到将A转换为B的排列:
pos = hash table (value -> position) of B
perm = []
for a in A:
if a not in pos: return "not the same!"
perm += [pos[a]]
此部分需要O(n)预期时间。
现在你必须找到排列的标志。您至少有两个选择:
实际上,您可以直接在输入数组上使用循环分解,这将产生一个很好的简短实现。
答案 1 :(得分:0)
一个有效的算法(O(n ^ 2))将如下(假设两个数组中都没有重复)。
bool same;
for(int i=0; i<L; i++)
{
same = false;
for(int j=0; j<L; j++) // see if A[i] is in B
if(A[i]==B[j])
{
same = true; // found A[i] in B
break;
}
if(!same) // A[i] was not found in B
break;
}
这里L
是数组的长度。在循环结束时,如果数组包含相同的元素,same
将为true
,否则为false
。希望这可以帮助。
PS:如果数组包含重复项,则此代码会告诉您A
是否包含B
。但是,您可以互换A
和B
的角色,并决定B
中是否包含A
。如果A
和B
中包含B
A
,A=B
,则{{1}}。
答案 2 :(得分:0)
这是一个通用的算法问题,还是您要求特定的(基于语言的)实现?
对于问题#1,只需在O(nlog(n))
中对每个数组进行排序,然后比较O(n)
中的数组。
如果输入值的范围不是很大,那么您可以使用直接哈希表并在O(n)
中执行排序阶段,从而将整体复杂度从O(nlog(n))
降低到{{1 }}
在Java中,您可以使用O(n)
实例来实现此目的。我不确定这个类的内部实现,但它可以为大范围的输入值实现相同的性能甚至。
对于问题#2,由于没有重复元素,所以排列总数为HashMap
。
您可以计算整个排列组中每个数组的排列ID,然后使用您计算的ID对来唯一地标识两个数组之间的映射。
例如,假设n!
和A = {3,2,1,4}
。
排列总数为24,因此每个排列都可以映射到0到23之间的ID:
B = {4,1,3,2}
1,2,3,4 ==> 0
1,2,4,3 ==> 1
1,3,2,4 ==> 2
1,3,4,2 ==> 3
1,4,2,3 ==> 4
1,4,3,2 ==> 5
2,1,3,4 ==> 6
2,1,4,3 ==> 7
2,3,1,4 ==> 8
2,3,4,1 ==> 9
2,4,1,3 ==> 10
2,4,3,1 ==> 11
3,1,2,4 ==> 12
3,1,4,2 ==> 13
3,2,1,4 ==> 14
3,2,4,1 ==> 15
3,4,1,2 ==> 16
3,4,2,1 ==> 17
4,1,2,3 ==> 18
4,1,3,2 ==> 19
4,2,1,3 ==> 20
4,2,3,1 ==> 21
4,3,1,2 ==> 22
4,3,2,1 ==> 23
已映射到ID 14 A
已映射到ID 19 如果您希望此函数产生单个值,则可以使用B
代替n!*id1+id2
。
或者,您可以定义映射函数f(A,B)以返回索引更改数组。
例如,假设id1,id2
和A = {3,2,1,4}
。
因此,B = {4,1,3,2}
应返回数组f({3,2,1,4},{4,1,3,2})
。