Algorithm 判断两个数组是否具有相同成员的算法
比较两个数组的成员是否相同的最佳算法是什么 假设没有重复项,成员可以按任何顺序排列,并且两个都没有排序Algorithm 判断两个数组是否具有相同成员的算法,algorithm,Algorithm,比较两个数组的成员是否相同的最佳算法是什么 假设没有重复项,成员可以按任何顺序排列,并且两个都没有排序 compare( [a, b, c, d], [b, a, d, c] ) ==> true compare( [a, b, e], [a, b, c] ) ==> false compare( [a, b, c], [a, b] ) ==> false 我想我能想到的最好的是O(n^2) function compare
compare(
[a, b, c, d],
[b, a, d, c]
) ==> true
compare(
[a, b, e],
[a, b, c]
) ==> false
compare(
[a, b, c],
[a, b]
) ==> false
我想我能想到的最好的是O(n^2)
function compare($foo, $bar) {
if (count($foo) != count($bar)) return false;
foreach ($foo as $f) {
foreach ($bar as $b) {
if ($f == $b) {
// $f exists in $bar, skip to the next $foo
continue 2;
}
}
return false;
}
return true;
}
您可以将一个元素加载到哈希表中,跟踪它有多少个元素。然后,循环第二个元素,检查它的每个元素是否都在哈希表中,并计算它有多少个元素。如果第二个数组中的每个元素都在哈希表中,并且两个长度匹配,则它们是相同的,否则它们不是。这应该是O(N) 要在存在重复项的情况下执行此操作,请跟踪每个元素已看到的数量。在第一个数组上循环时递增,在第二个数组上循环时递减。在第二个数组上循环期间,如果在哈希表中找不到某些内容,或者如果计数器已经为零,则它们是不等的。还要比较总计数
在存在重复项的情况下工作的另一种方法是对两个数组进行排序并进行线性比较。这应该是O(N*log(N))。显而易见的答案是:
你会使用哪一种取决于你是否能先对列表进行排序,以及你是否有一个好的散列算法。我建议先使用排序,然后将两者都排序。然后比较每个数组的第一个元素,然后比较第二个元素,依此类推
如果发现不匹配,可以停止。如果先对两个数组进行排序,则会得到O(N log(N))。最好的方法可能是使用哈希映射。由于向hashmap中插入是O(1),因此从一个数组构建hashmap需要O(n)。然后有n个查找,每个查找取O(1),因此需要另一个O(n)操作。总之,它是O(n) 在python中:
def comparray(a, b):
sa = set(a)
return len(sa)==len(b) and all(el in sa for el in b)
忽略C#中的内置方法,您可以执行以下操作: 在最好的情况下是O(1),在最坏的情况下是O(N)(每个列表)
public bool MatchArrays(object[] array1, object[] array2)
{
if (array1.length != array2.length)
return false;
bool retValue = true;
HashTable ht = new HashTable();
for (int i = 0; i < array1.length; i++)
{
ht.Add(array1[i]);
}
for (int i = 0; i < array2.length; i++)
{
if (ht.Contains(array2[i])
{
retValue = false;
break;
}
}
return retValue;
}
private boolean compare(List listA, List listB){
if (listA.size()==0||listA.size()==0) return true;
List runner = new ArrayList();
List maxList = listA.size()>listB.size()?listA:listB;
List minList = listA.size()>listB.size()?listB:listA;
int macthes = 0;
List nextList = null;;
int maxLength = maxList.size();
for(int i=0;i<maxLength;i++){
for (int j=0;j<2;j++) {
nextList = (nextList==null)?maxList:(maxList==nextList)?minList:maList;
if (i<= nextList.size()) {
MatchingItem nextItem =new MatchingItem(nextList.get(i),nextList)
int position = runner.indexOf(nextItem);
if (position <0){
runner.add(nextItem);
}else{
MatchingItem itemInBag = runner.get(position);
if (itemInBag.getList != nextList) matches++;
runner.remove(position);
}
}
}
}
return maxLength==macthes;
}
public Class MatchingItem{
private Object item;
private List itemList;
public MatchingItem(Object item,List itemList){
this.item=item
this.itemList = itemList
}
public boolean equals(object other){
MatchingItem otheritem = (MatchingItem)other;
return otheritem.item.equals(this.item) and otheritem.itemlist!=this.itemlist
}
public Object getItem(){ return this.item}
public Object getList(){ return this.itemList}
公共布尔匹配数组(对象[]数组1,对象[]数组2)
{
if(array1.length!=array2.length)
返回false;
bool-retValue=true;
HashTable ht=新的HashTable();
for(int i=0;i
假设您不想干扰原始阵列,并且需要考虑空间,另一个比排序两个阵列使用更少空间的O(n.log(n))解决方案是:
在实践中,我会使用散列。一些人断言散列的O(1)行为,导致他们得出结论,基于散列的解决方案是O(N)。典型的插入/查找可能接近O(1),一些散列方案保证最坏情况下的O(1)查找,但最坏情况下的插入——在构建散列时——不是O(1)。给定任何特定的哈希数据结构,都会有一些输入会产生病理行为。我怀疑存在哈希数据结构,其最坏情况组合为O(N.log(N))时间和O(N)空间的[insert-N-elements然后lookup-N-elements]解决方案显然取决于您的约束条件。如果它是一个小数据集,排序、哈希或蛮力比较(如posted)都将非常相似。因为您知道您处理的是整数值,所以可以得到O(n)排序时间(例如基数排序),哈希表也将使用O(n)和往常一样,每种方法都有缺点:排序要么需要复制数据,要么对数组进行破坏性排序(丢失当前排序)如果您想节省空间。哈希表显然会有内存开销来创建哈希表。如果您使用nickf的方法,您可以在几乎没有内存开销的情况下完成此操作,但您必须处理O(n2)运行时。您可以选择最适合您的目的。在这里进行深入讨论,但是: 已排序列表 如前所述,排序可以是O(nlogn)。为了澄清这一点,有两个列表并不重要,因为:
O(2*nlogn)==O(nlogn)
,然后比较每个元素就是另一个O(n),所以对这两个元素进行排序然后比较每个元素就是O(n)+O(nlogn),即:O(nlogn)
哈希表:
将第一个列表转换为哈希表是O(n),用于读取+哈希表中存储的成本,我猜可以估计为O(n),得到O(n)。然后,您必须检查生成的哈希表中其他列表中的每个元素是否存在,即(至少?)O(n)(假设检查哈希表中某个元素的存在性是恒定的)。总之,我们最终得到了检查的O(n)
Java列表接口,因为每个对应的元素相等
有趣的是,Java集合接口定义函数
最后,Java语言支持这种行为。实现应该非常高效,但文档中没有提到性能。(找不到源代码的链接,
public bool MatchArrays(object[] array1, object[] array2)
{
if (array1.length != array2.length)
return false;
long signature1 = 0;
long signature2 = 0;
for (i=0;i<array1.length;i++) {
signature1=CommutativeOperation(signature1,array1[i].getHashCode());
signature2=CommutativeOperation(signature2,array2[i].getHashCode());
}
if (signature1 != signature2)
return false;
return MatchArraysTheLongWay(array1, array2);
}
public long CommutativeOperation(long oldValue, long newElement) {
return oldValue + newElement;
}
private boolean compare(List listA, List listB){
if (listA.size()==0||listA.size()==0) return true;
List runner = new ArrayList();
List maxList = listA.size()>listB.size()?listA:listB;
List minList = listA.size()>listB.size()?listB:listA;
int macthes = 0;
List nextList = null;;
int maxLength = maxList.size();
for(int i=0;i<maxLength;i++){
for (int j=0;j<2;j++) {
nextList = (nextList==null)?maxList:(maxList==nextList)?minList:maList;
if (i<= nextList.size()) {
MatchingItem nextItem =new MatchingItem(nextList.get(i),nextList)
int position = runner.indexOf(nextItem);
if (position <0){
runner.add(nextItem);
}else{
MatchingItem itemInBag = runner.get(position);
if (itemInBag.getList != nextList) matches++;
runner.remove(position);
}
}
}
}
return maxLength==macthes;
}
public Class MatchingItem{
private Object item;
private List itemList;
public MatchingItem(Object item,List itemList){
this.item=item
this.itemList = itemList
}
public boolean equals(object other){
MatchingItem otheritem = (MatchingItem)other;
return otheritem.item.equals(this.item) and otheritem.itemlist!=this.itemlist
}
public Object getItem(){ return this.item}
public Object getList(){ return this.itemList}
A:array
B:array
C:hashtable
if A.length != B.length then return false;
foreach objA in A
{
H = objA;
if H is not found in C.Keys then
C.add(H as key,1 as initial value);
else
C.Val[H as key]++;
}
foreach objB in B
{
H = objB;
if H is not found in C.Keys then
return false;
else
C.Val[H as key]--;
}
if(C contains non-zero value)
return false;
else
return true;