You have a list of family relationships between father and son. Every element on this list has two elements. The first is the father's name, the second is a son’s name. All names in the family are unique. Check if the family tree is correct. There are no strangers in the family tree. All connections in the family are natural.
Input: list of lists. Every element has two strings. List has at least one element
Output: bool. Is family tree correct.
如题所示,给定一个包含n个二元列表的列表,每一个子列表包含一个“父子关系”,需要判断给定列表是否构成一个合理的家族。(既不存在陌生人,也不存在关系冲突——如互为父子),返回布尔值。
分析:
两种情况应该分别处理,存在陌生人则返回False,存在关系冲突也返回False,否则遍历完成后返回True。
陌生人情形:
我们考虑进行第一次遍历——首先将第一个列表内的父子加入一个新列表,对于剩下的列表,当新的父子对之一存在于新列表中时,才将新的父子对加入新列表并去重,最差时间复杂度为O(n^2),因此可以在while循环中加入时钟判断,当超过阈值时返回False
父子矛盾情形:
考虑将新列表维护为一个字典,即——父亲的value总是比儿子的小1,当加入新父子对时,若二者均存在于列表中,并发现value值存在矛盾,则返回False。
逻辑通过情形:
在时钟阈值内,当原列表长度计数为0时,返回True。
def is_family(tree):
length = len(tree)
if length == 1:
print('Only one pair!')
return True
clock = length**2 # 时钟
check_dict = {tree[0][0]:1,tree[0][1]:2} # 判断字典
length -= 1 # 剩余未判断过的父子对
while True:
for pairs in tree:
clock -= 1 # 进行了一次判断
if pairs[0] not in check_dict and pairs[1] not in check_dict: # 不能确定是否陌生人,先跳过
pass
elif pairs[0] in check_dict and pairs[1] in check_dict: # 若已存在于判断字典中,判断关系序列是否正确
if check_dict[pairs[0]] != check_dict[pairs[1]] - 1 :
print('Wrong relationship')
return False
elif pairs[0] in check_dict: # 若父亲已存在于字典中,将儿子添加进入
length -= 1
check_dict[pairs[1]] = check_dict[pairs[0]] + 1
elif pairs[1] in check_dict: # 若儿子已存在于字典中,判断是否有两个父亲的冲突
for keys in check_dict:
if check_dict[keys] == check_dict[pairs[1]] - 1:
print("Who is your daddy?")
return False
length -= 1
check_dict[pairs[0]] = check_dict[pairs[1]] - 1 # 未冲突,将父亲添加入字典
if length == 0: # 当所有的父子对均被判断过
print('Is Family')
return True
if clock == 0: # 当时钟超过阈值
print('Stranger!')
return False
上述就是我的思路,感觉在时间复杂度上可以优化,例如维护一个包含已判断过的父子对的列表中位置序号的列表,使用enumerate方法,理论上最差时间为sigma(n-1)*2 = n^2-n
希望读者有更优的解法可以赐教。