我正在分析Codility提供的python中的example计数
我不理解这个算法的最后一个循环(最后5行)中使用的逻辑。
有人可以帮忙吗?
问题:
您将获得一个整数
m
(1 < m < 1000000
)和两个非空, 零索引数组A
和B
n
个整数,a0
,a1
,..., 分别为an−1
和b0
,b1
,...,bn−1
(0 < ai
,bi < m
)。 目标是检查是否存在可以进行的交换操作 以这样的方式对这些数组执行,即元素的总和 数组A
等于交换后数组B
中元素的总和。通过 交换操作我们的意思是从数组A
和一个中选择一个元素 数组B
中的元素并进行交换。
解决方案:
def counting(A, m):
n = len(A)
count = [0] * (m + 1)
for k in xrange(n):
count[A[k]] += 1
return count
def fast_solution(A, B, m):
n = len(A)
sum_a = sum(A)
sum_b = sum(B)
d = sum_b - sum_a
if d % 2 == 1:
return False
d //= 2
count = counting(A, m)
for i in xrange(n):
if 0 <= B[i] - d and B[i] - d <= m and count[B[i] - d] > 0:
return True
return False
答案 0 :(得分:2)
我建议你再次阅读练习中给出的解释。它已经解释了算法的工作原理。但是,如果你仍然遇到问题,那就拿一张纸和一些非常简单的示例数组,逐步完成解决方案。
例如,请A = [6, 6, 1, 2, 3]
和B = [1, 5, 3, 2, 1]
。
现在让我们来看看算法。
我假设您了解此方法的工作原理:
def counting(A, m):
n = len(A)
count = [0] * (m + 1)
for k in xrange(n):
count[A[k]] += 1
return count
它只返回一个带有计数的列表,如练习中所述。对于列表A和m = 10,它将返回:
[0, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0]
然后我们通过主方法fast_solution(A, B, m)
:
n = 11
(这将在循环中使用)
A的总和等于18
,B的总和等于12
。
差异d
是-6
(sum_b - sum_a),它是偶数。请注意,如果差异为奇数,则没有可用的交换,结果为False。
然后d
除以2
。它变为-3
。
对于A,我们得到计数[0, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0]
(如前所述)。
然后我们使用xrange
迭代列表B并检查条件(循环从0到最多但不包括11)。让我们一步一步检查:
i = 0
,B[0] - (-3)
是1 + 3 = 4
。 4大于或等于0且小于或等于10(记住,我们选择m
为10
)。但是,count[4]
为0且不大于0(注意列表count
从索引0
开始)。条件失败,我们走得更远。
i = 1
,B[1] - (-3)
是5 + 3 = 8
。 8大于或等于0且小于或等于10.但是,count[8]
为0且条件失败。
i = 2
,B[2] - (-3)
是3 + 3 = 6
。 6大于0且小于10.另外count[6]
是2并且它大于0.所以我们找到了数字。循环停止,返回True。这意味着B中有一个这样的数字,可以用A中的数字交换,这样A的总和就等于B的总和。的确,如果我们将A中的6与B中的3交换,那么它们的总和就变成了等于15.
希望这有帮助。
答案 1 :(得分:1)
我不确定我的想法是否正确。这是我的理解:
def counting(A, m):
n = len(A)
count = [0] * (m + 1)
for k in xrange(n):
count[A[k]] += 1
return count # this essentially build a counter
def fast_solution(A, B, m):
n = len(A)
sum_a = sum(A)
sum_b = sum(B)
d = sum_b - sum_a
if d % 2 == 1:
return False
d //= 2
count = counting(A, m) # get the dict
for i in xrange(n):
if 0 <= B[i] - d and B[i] - d <= m and count[B[i] - d] > 0:
# the first two conditions are to verify that B[i]-d exists as a key (index) in counter.
# then check if there actually exists the value.
# if count > 0, then you can swap the two to get same sum
return True
return False
或重写以获得:
def counting(A, m):
count = collections.Counter()
for i in A:
count[i] += 1
return count
def fast_solution(A, B, m):
n = len(A)
sum_a = sum(A)
sum_b = sum(B)
d = sum_b - sum_a
if d % 2 == 1:
return False
d //= 2
count = counting(A, m) # get the dict
for i in B:
if count[i-d]:
return True
return False
但无论如何,这段代码只是通过单一交换来检查解决方案的存在,请务必检查这是否是您想要的。