我需要生成三个自然数,其总和为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
非常大,大约500
和x, y, z
小于200.目前我有3个变量(i, j, k)
来自3个范围。可以使用列表推导中的两个循环来完成吗?
答案 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 - j
或0
范围内循环,如下所示:
1
请注意,在这种情况下,您不必再检查for k in range(max(1, n - i - j), min(z + 1, n - i - j + 1)):
l.append((i, j, k))
。