因此,我正在HackerHank上进行初学者挑战,而红宝石的一种奇怪行为令我感到困惑。
挑战是:查找并计算数组中有多少对。 (袜子对)
这是我的代码。
n = 100
ar = %w(50 49 38 49 78 36 25 96 10 67 78 58 98 8 53 1 4 7 29 6 59 93 74 3 67 47 12 85 84 40 81 85 89 70 33 66 6 9 13 67 75 42 24 73 49 28 25 5 86 53 10 44 45 35 47 11 81 10 47 16 49 79 52 89 100 36 6 57 96 18 23 71 11 99 95 12 78 19 16 64 23 77 7 19 11 5 81 43 14 27 11 63 57 62 3 56 50 9 13 45)
def sockMerchant(n, ar)
counter = 0
ar.each do |item|
if ar.count(item) >= 2
counter += ar.count(item)/2
ar.delete(item)
end
end
counter
end
print sockMerchant(n, ar)
问题是,这算不上好。运行该函数后,它的内部数组 ar 中仍然有可数的对,我通过再次运行来证明这一点。
还有更多。如果对数组排序,则其行为会有所不同。
对我来说这没有意义。
您可以检查此链接上的行为
答案 0 :(得分:5)
您要在集合中进行迭代时删除项目-希望发生不良情况。简而言之,如果您不想遇到此类问题,请不要这样做,请参阅:
> arr = [1,2,1]
# => [1, 2, 1]
> arr.each {|x| puts x; arr.delete(x) }
# 1
# => [2]
我们在迭代中从未得到2
。
一个简单的解决方案,即您的代码的一个很小的变化,如下所示:
def sock_merchant(ar)
ar.uniq.sum do |item|
ar.count(item) / 2
end
end
基本上是在寻找所有独特的袜子,然后为每只袜子计数。
请注意,由于数组的每个唯一元素n^2
的复杂度为n
,因此必须遍历整个数组才能找到等于n
的所有元素
另一种方法是,先将所有袜子分组,然后检查我们每种袜子有几对:
ar.group_by(&:itself).sum { |k,v| v.size / 2 }
作为ar.group_by(&:itself)
的缩写,ar.group_by { |x| x.itself }
将遍历数组并创建一个哈希,如下所示:
{"50"=>["50", "50"], "49"=>["49", "49", "49", "49"], "38"=>["38"], ...}
通过调用sum
,我们将对其进行迭代,将找到的元素(/2
)的数量相加。