问题重述
n 个整数两两相加可以得到 n(n - 1) / 2 个和。根据这些和找出原来的 n 个整数。按非降序排序返回这 n 个数,如果无解,输出 "Impossible"。
思路分析
-
排列组合:
- 由于不知道
sums列表中各个和对应哪两个原始整数的和,因此首先想到的是尝试sums列表的所有可能排列。 - 使用
itertools.permutations生成sums的所有排列,然后逐一检查每种排列是否可能对应到原始的整数序列。
- 由于不知道
-
利用三元组推导:
- 假设
x1, x2, ..., xn是原始的整数序列。 - 从
sums的一个排列中,选取三个和a, b, c(其中c可以是任意不与a, b同时作为原始整数对的和的和,例如,如果sums长度为len(sums),则可以选择a = perm[0],b = perm[1],c = perm[len(sums)-1])。 - 假设
a = x1 + x2,b = x1 + x3,c = x2 + x3(注意:这里的假设是基于题目能够通过这种方式求解的隐含条件,实际上题目已经保证了存在这样的解)。 - 通过这三个等式,可以解出
x1 = (a + b - c) // 2(注意要整除,这是判断当前排列是否可行的一个条件)。
- 假设
-
推导其他整数:
- 一旦知道了
x1,就可以通过sums列表中的其他和来推导x2, x3, ..., xn。 - 对于
sums中的每个和s,如果它不等于x1 + x1(即不是x1自加的和),那么它必然等于x1 + xi(其中xi是某个未知的原始整数)。 - 因此,可以通过
s - x1得到xi。
- 一旦知道了
-
验证:
- 得到所有原始整数后,需要验证这些整数两两相加的和是否确实等于
sums列表中的每个和。 - 如果验证通过,则返回这些整数(按非降序排序);如果验证失败,则继续检查下一个排列。
- 得到所有原始整数后,需要验证这些整数两两相加的和是否确实等于
-
返回结果:
- 如果遍历了
sums的所有排列后都没有找到可行的解,则返回 "Impossible"。
- 如果遍历了
代码分析
1.生成排列并尝试推导原始整数
import itertools
def solution(n, sums):
for perm in itertools.permutations(sums):
# perm[0] 是 x1 + x2, perm[1] 是 x1 + x3, perm[n-1] 是 x2 + x3
x1 = (perm[0] + perm[1] - perm[n-1]) // 2
x = [x1]
for i in range(n-1):
xi = perm[i] - x1
x.append(xi)
- 使用
itertools.permutations(sums)生成sums列表的所有排列,并通过循环遍历每个排列。 - 在每个排列中,我们假设
perm[0]是x1 + x2,perm[1]是x1 + x3,而perm[n-1]是x2 + x3(这里的n-1是基于题目能够通过这种方式求解的隐含条件,即我们假设sums列表中至少包含这三个和,并且它们的排列能够让我们解出x1)。 - 通过这三个和,我们可以推导出
x1 = (perm[0] + perm[1] - perm[n-1]) // 2。注意,这里使用了整除//,因为题目保证了这样的计算能够得到整数结果。 - 一旦得到了
x1,我们就可以通过perm[i] - x1来推导其他原始整数xi,并将它们存储在列表x中。 2.验证推导结果并返回最终结果
index = 0
valid = True
for i in range(n):
for j in range(i+1, n):
if x[i] + x[j] != perm[index]:
valid = False
break
index += 1
if not valid:
break
if valid:
return " ".join(map(str, sorted(x)))
return "Impossible"
- 我们定义了一个变量
valid来标记当前推导的原始整数序列是否有效。 - 使用两个嵌套的循环来遍历推导出的原始整数序列
x的所有可能的两两组合,并检查它们的和是否等于排列perm中的对应和。 - 如果发现任何不匹配的和,就将
valid设置为False并跳出循环。 - 如果所有的和都匹配,即
valid保持为True,则对推导出的原始整数序列x进行排序,并将其转换为字符串形式返回。 - 如果遍历了所有的排列都没有找到有效的原始整数序列,则返回"Impossible"。
总结
上述代码定义了一个函数solution,该函数接收两个参数:整数n和列表sums。它通过枚举sums的所有排列,尝试推导出n个原始整数。验证成功后,返回排序后的整数序列;若所有排列均不满足条件,则返回"Impossible"。