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
希望读者有更优的解法可以赐教。