python:用于在两个数组之间交换元素的算法

时间:2016-10-27 02:26:15

标签: python

我正在分析Codility提供的python中的example计数

我不理解这个算法的最后一个循环(最后5行)中使用的逻辑。
有人可以帮忙吗?

问题:

  

您将获得一个整数m1 < m < 1000000)和两个非空,   零索引数组AB n个整数,a0a1,...,   分别为an−1b0b1,...,bn−10 < aibi < 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

2 个答案:

答案 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 = 0B[0] - (-3)1 + 3 = 4。 4大于或等于0且小于或等于10(记住,我们选择m10)。但是,count[4]为0且不大于0(注意列表count从索引0开始)。条件失败,我们走得更远。

i = 1B[1] - (-3)5 + 3 = 8。 8大于或等于0且小于或等于10.但是,count[8]为0且条件失败。

i = 2B[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

但无论如何,这段代码只是通过单一交换来检查解决方案的存在,请务必检查这是否是您想要的。