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

时间:2012-04-04 01:43:38

标签: arrays algorithm permutation

如果我有两个不同的数组,我所能做的就是检查数组中的两个元素是否相等(换句话说,没有比较函数(超出等于)对元素进行排序),是否有效检查一个数组是否是另一个数组的排列的方法吗?

7 个答案:

答案 0 :(得分:4)

像Jared的蛮力解决方案应该有效,但它是O(n ^ 2)。

如果元素是可以清除的,则可以实现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

根据字典的实现方式(作为散列集与树集),这将采用散列集的O(n)或树集的O(n log n)。

答案 1 :(得分:3)

这种实现可能是错误的,但一般的想法应该是正确的。我刚刚开始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

答案 2 :(得分:0)

如果您的对象类型的散列是有意义的,您可以使用临时散列集来插入数组A中的所有项。然后在迭代数组B时,确保每个项都已经在临时散列集中。

这应该比天真的嵌套O(n ^ 2)循环更快(O(n))。 (除了小的或琐碎的数据集,一个更简单的天真算法可能会胜过它)

请注意,这将占用O(n)额外的内存,并且这种方法只有在您没有重复项时才会起作用(或者不想将它们作为比较的一部分计算)

答案 3 :(得分:0)

假设两个数组长度相等且一个元素可能多次出现在数组中,你可以创建另一个长度相同的数组,boolean initialized为false。

然后遍历其中一个数组并为每个元素检查该元素是否出现在另一个数组中相应的布尔值为假的位置 - 如果是,则将相应的布尔值设置为true。如果第一个数组中的所有元素都可以这样计算,那么两个数组是相等的,否则不是(并且你发现至少有一个差异)。

内存要求为O(n),时间复杂度为O(n ^ 2)

答案 4 :(得分:0)

因为我还没有发表评论(没有足够的代表),我在这里只是提到它作为对其他答案之一的回复:Python的set()对于对象不能很好地工作。

如果您有可以清除的对象,则此代码应该适合您:

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

构造a中对象的hashmap及其出现次数。对于b中的每个元素,如果元素不在hashmap中或者出现不匹配,则它不是排列。否则,这是一种排列。

>>> 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

答案 5 :(得分:0)

// 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;​
        }

答案 6 :(得分:0)

以前的答案很好。 只需在Python中添加,就像在Python中一样,就非常简单。

如果:

  1. 数组的长度相等。
  2. 数组B中没有不存在于数组A中的元素。
  3. 在数组B中没有比在数组A中出现更多的元素。

数组是彼此的排列

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