简体   繁体   English

如何判断两个 arrays 是否是彼此的排列(无法对它们进行排序)

[英]How to tell if two arrays are permutations of each other (without the ability to sort them)

If I have two different arrays and all I can do is check whether two elements in the arrays are equal (in other words, there is no comparison function (beyond equals) for the elements to sort them), is there any efficient way to check whether one array is a permutation of the other?如果我有两个不同的 arrays 并且我所能做的就是检查 arrays 中的两个元素是否相等(换句话说,没有比较 function (超出等于)的元素对它们进行排序),是否有任何有效的方法来检查一个数组是否是另一个数组的排列?

Words Like Jared's brute force solution should work, but it is O(n^2).像 Jared 的蛮力解决方案这样的话应该可行,但它是 O(n^2)。

If the elements are hashable, you can achieve O(n).如果元素是可散列的,则可以实现 O(n)。

def isPermutation(A, B):
    """
    Computes if A and B are permutations of each other.
    This implementation correctly handles duplicate elements.
    """
    # make sure the lists are of equal length
    if len(A) != len(B):
        return False

    # keep track of how many times each element occurs.
    counts = {}
    for a in A:
        if a in counts: counts[a] = counts[a] + 1
        else: counts[a] = 1

    # if some element in B occurs too many times, not a permutation
    for b in B:
        if b in counts:
            if counts[b] == 0: return False
            else: counts[b] = counts[b] - 1
        else: return False

    # None of the elements in B were found too many times, and the lists are
    # the same length, they are a permutation
    return True

Depending on how the dictionary is implemented (as a hashset vs a treeset), this will take either O(n) for hashset or O(n log n) for treeset.根据字典的实现方式(作为哈希集与树集),哈希集的复杂度为 O(n),树集的复杂度为 O(n log n)。

This implementation might be wrong, but the general idea should be correct.这种实现可能是错误的,但总体思路应该是正确的。 I am just starting python, so this may also be an unconventional or non-pythonic style.我刚刚开始python,所以这也可能是一种非常规或非pythonic风格。

def isPermutation(list1, list2):
    # make sure the lists are of equal length
    if (len(list1) is not len(list2)):
        return False

    # keep track of what we've used
    used = [False] * len(list1)

    for i in range(len(list1)):
        found = False

        for j in range(len(list1)):
            if (list1[i] is list2[j] and not used[j]):
                found = True
                used[j] = True
                break

        if (not found):
            return False

    return True

If hashing for your object type makes sense, you could use a temp hash set to insert all the items from array A. Then while iterating over array B, make sure each item is already in the temp hash set.如果您的 object 类型的散列有意义,您可以使用临时 hash 集插入数组 A 中的所有项目。然后在遍历数组 B 时,确保每个项目都已在临时 hash 集中。

This should be faster ( O(n) ) than a naive nested O(n^2) loop.这应该比天真的嵌套 O(n^2) 循环更快( O(n) )。 (Except for small or trivial data sets, where a simpler naive algo might outperform it) (除了小型或琐碎的数据集,更简单的朴素算法可能会胜过它)

Note that this will take O(n) extra memory, and that this approach will only work if you dont have duplicates (or dont want to count them as part of the comparison)请注意,这将花费 O(n) 额外的 memory,并且此方法仅在您没有重复项(或不想将它们作为比较的一部分)时才有效

Assuming the two arrays are equal length and an element could be appearing the arrays more than once, you could create another array of the same length of type boolean initialized to false.假设两个 arrays 的长度相等,并且一个元素可能不止一次出现在 arrays 中,您可以创建另一个长度相同的 boolean 类型的数组并初始化为 false。

Then iterate though one of the arrays and for each element check whether that element appears in the other array at a poistion where the corresponding boolean is false -- if it does, set the corresponding boolean to true.然后遍历 arrays 之一,并针对每个元素检查该元素是否出现在另一个数组中对应的 boolean 为假的位置——如果出现,则将对应的 boolean 设置为真。 If all elements in the first array can be accounted for this way, the two arrays are equal, otherwise not (and you found at least one difference).如果第一个数组中的所有元素都可以这样计算,则两个 arrays 相等,否则不相等(您发现了至少一个差异)。

The memory requirement is O(n), the time complexity is O(n^2) memory要求是O(n),时间复杂度是O(n^2)

Because I can't comment yet (not enough rep), I'll just mention this here as a reply to one of the other answers: Python's set() doesn't work all that well with objects.因为我还不能发表评论(没有足够的代表),我只是在这里提到这个作为对其他答案之一的答复:Python 的 set() 不能很好地处理对象。

If you have objects that are hashable, this code should work for you:如果您有可散列的对象,则此代码应该适合您:

def perm(a, b):
        dicta = {}; dictb = {}
    for i in a:
            if i in dicta: dicta[i] += 1
            else: dict[i] = 1
    for i in b:
        if i in dictb: dictb[i] += 1
        else: dict[i] = 1
    return dicta == dictb

Construct a hashmap of objects in a and the number of times they occur.构造a中hashmap个对象及其出现次数。 For each element in b, if the element is not in the hashmap or the occurrences don't match, it is not a permutation.对于 b 中的每个元素,如果该元素不在 hashmap 中或出现次数不匹配,则它不是排列。 Otherwise, it is a permutation.否则,它是一个排列。

>>> perm([1,2,4], [1,4,2])
True
>>> perm([1,2,3,2,1], [1,2,1,2,3])
True
>>> perm([1,2,4], [1,2,2])
False

// C# code, l1 and l2 are non-sorted lists // C# 代码,l1 和 l2 是非排序列表

        private static bool AreListContainedEachOther(List<int> l1, List<int> l2)
        {​
            if (l1.Equals(null) || l2.Equals(null))​
                return false;​
​
            bool isContained = true;​
​
            foreach (int n in l1)​
            {​
                if (!l2.Contains(n))​
                    return false;​
            }​
​
            return isContained;​
        }

The previous answers are great.前面的回答都很棒。 Just adds, in Python, like in Python, it's really simple.补充一下,在Python,和Python一样,真的很简单。

If:如果:

  1. The length of the arrays is equal. arrays 的长度相等。
  2. There are no elements in array B that do not exist in array A.数组 B 中没有不存在于数组 A 中的元素。
  3. There are no elements that have more occurrences in Array B than in Array A.没有元素在数组 B 中出现的次数多于在数组 A 中出现的次数。

The arrays are permutations of each other arrays 是彼此的排列

from collections import defaultdict


def is_permutation(a, b):
    if len(a) != len(b):
        return False
    counts = defaultdict(int)
    for element in a:
        counts[element] += 1
    for element in b:
        if not counts[element]:
            return False
        counts[element] -= 1
    return True

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM