📅  最后修改于: 2023-12-03 15:37:23.032000             🧑  作者: Mango
给定三个正整数 A, B, C 和一个正整数 N,现在有一个长度为 N 的数字序列 [1, 2, 3, ..., N],你需要在其中选择 K 个三元组 (A, B, C) 来构建一棵树,要求从 A 到 C 的任何路径都不能包含 B。请你编写一个函数,返回是否有符合条件的树。
输入一行包含四个正整数 N、K、A 和 C。
如果不存在符合条件的树,则输出一个空列表 []。否则输出一个长度为 N 的列表,第 i 个元素表示数字 i 在树中的父节点编号。
def build_tree(n: int, k: int, a: int, c: int) -> List[int]:
4 2 1 4
[0, 1, 2, 1]
3 2 1 3
[]
本题可以采用贪心思想。
如果要求从 A 到 C 的任何路径都不能包含 B,那么只有两种情况:
对于第一种情况,我们可以把 B 连接到 A 和 C 的公共祖先上。如果 A 和 C 本身就是一对祖先后代关系,则连接 B 和 A(或 C)的父节点即可。
对于第二种情况,我们需要找到一个距离 A 和 C 路径越远越好的节点 B。可以考虑在直线 AC 上均匀地选取 K 个点,然后在这些点中选择距离 AC 路径最远的点作为 B。
from typing import List
def build_tree(n: int, k: int, a: int, c: int) -> List[int]:
# 处理两个特殊情况
if k >= n or a == c or k == 0:
return []
if k == 1:
return [i if i != a else c for i in range(1, n + 1)]
# 计算选择的 K 个点
if k % 2 == 1:
points = [i for i in range(1, n + 1, n // k)]
else:
points = [(i - 0.5) // k * n + 0.5 for i in range(1, k + 1)]
points = [int(round(x, 0)) for x in points]
# 找到距离 AC 最远的点作为 B
b = max(points, key=lambda x: min(abs(x - a), abs(x - c)))
points.remove(b)
# 构建树
tree = [0] * (n + 1)
for i in range(1, n + 1):
if i != a and i != c:
j = min(points, key=lambda x: abs(x - i))
tree[i] = j
points.remove(j)
tree[a] = c
tree[b] = (a + c - b) // 2
return tree[1:]
print(build_tree(4, 2, 1, 4)) # [0, 1, 2, 1]
print(build_tree(3, 2, 1, 3)) # []