我一直在考虑以下问题 - 有两个数组,我需要找到不常见的元素,例如:
a = [1,2,3,4]
b = [1,2,4]
预期答案为[3]
。
到目前为止,我一直这样做:
a.select { |elem| !b.include?(elem) }
但它给了我O(N ** 2)
时间复杂性。我确信它可以更快地完成;)
另外,我一直在考虑以某种方式得到它(使用与&
相反的方法,它提供了2个数组的公共元素):
a !& b #=> doesn't work of course
另一种方法可能是添加两个数组并使用类似于uniq
的方法查找唯一元素,以便:
[1,1,2,2,3,4,4].some_method #=> would return 3
答案 0 :(得分:21)
最简单的(仅使用已经存在的数组和库存数组方法)解决方案是union的differences:
a = [1,2,3,4]
b = [1,2,4]
(a-b) | (b-a)
=> [3]
这可能会或可能不会比O(n**2)
更好。还有其他选择可能会提供更好的表现(见其他答案/评论)。
编辑:这是一种快速实现的排序和迭代方法(假设没有数组有重复的元素;否则需要根据在这种情况下需要的行为进行修改)。如果有人能想出一个更短的方法来做,我会感兴趣。限制因素是使用的排序。我假设Ruby使用某种Quicksort,因此复杂度平均为O(n log n)
,最坏情况可能为O(n**2)
;如果数组已经排序,那么当然可以删除对sort
的两次调用,它将在O(n)
中运行。
def diff a, b
a = a.sort
b = b.sort
result = []
bi = 0
ai = 0
while (ai < a.size && bi < b.size)
if a[ai] == b[bi]
ai += 1
bi += 1
elsif a[ai]<b[bi]
result << a[ai]
ai += 1
else
result << b[bi]
bi += 1
end
end
result += a[ai, a.size-ai] if ai<a.size
result += b[bi, b.size-bi] if bi<b.size
result
end
答案 1 :(得分:17)
正如@iamnotmaynard在评论中指出的那样,传统上这是一种集合操作(称为对称差异)。 Ruby的Set类包含了这个操作,因此表达它的最常用的方法是使用Set:
Set.new(a) ^ b
这应该给出O(n)性能(因为集合成员资格测试是恒定时间)。
答案 2 :(得分:10)
a = [1, 2, 3]
b = [2, 3, 4]
a + b - (a & b)
# => [1, 4]
答案 3 :(得分:0)
Array diffgences的解决方案如下:
a = [1, 2, 3]
b = [2, 3, 4]
(a - b) | (b - a)
# => [1, 4]
您还可以阅读有关Array coherences
的博客文章