生成3个数字,其总和为n

时间:2015-07-10 09:37:58

标签: python list-comprehension

我需要生成三个自然数,其总和为n。第一个数字可以是最大x,第二个数字可以是最大y,最终数字可以是最大z。目前我在做这个

def f(n):
    return [(i, j, k)
            for i in range(x+1)
            for j in range(y+1)
            for k in range(z+1)
            if i + j + k == n]

但是n非常大,大约500x, y, z小于200.目前我有3个变量(i, j, k)来自3个范围。可以使用列表推导中的两个循环来完成吗?

2 个答案:

答案 0 :(得分:3)

是的,

你可以计算第三个数字并检查它是否在正确的范围内(Martijn Pieters♦)。

[(i, j, n - i - j) for i in range(x+1) for j in range(y+1) if 0 <= n - i - j <= z]

答案 1 :(得分:2)

你需要做的是根据第一个(j)和最后一个(i)的值约束第二个变量(k),具体取决于2第一:

l = []
for i in range(1, x + 1):
    for j in range(max(1, n - x - z), min(y + 1, n - x - 1)): # No need to go above n - x - 1or bellow n - x - z
        # For k, you do not even need a loop since it is constrained by i and j
        k = n - i - j 
        if 0 < k <= z:
            l.append((i, j, k))

我没有使用列表压缩来详细说明代码,但当然可以:

[(i, j, n - i - j) for i in range(1, x + 1) for j in range(max(1, n - x - z), min(y + 1, n - x - 1)) if 0 < n - i - j <= z]

x等于1(全局循环中的第一个值)时,y的范围从n - x - z = 500 - 1 - 200 = 299变为200,即您没有甚至可以输入y循环,这是正常的,因为您需要x至少100才能达到500(因为y和{{ 1}}最多为z)。

每次遇到这种问题时,请考虑一下«如何根据已分配的变量减少当前变量的域? »。

顺便说一句,执行200分配相当于在k = n - i - j0范围内循环,如下所示:

1

请注意,在这种情况下,您不必再检查for k in range(max(1, n - i - j), min(z + 1, n - i - j + 1)): l.append((i, j, k))