这是我建议的解决方案:要点是跟踪子树的当前节点数、当前高度和最大高度,直到该点为止。
在当前节点数和高度的情况下,可以通过其直接子节点各自的信息来计算根节点的节点数和高度,同时考虑子节点高度之间的关系以及它们是否是完美子树。
解是O(n)时间复杂度和O(h)空间复杂度(函数调用栈从根通过唯一路径对应到当前节点)。
这是此解决方案的 Python 代码,您可以通过示例找到完整的要点here:
from collections import namedtuple
class BTN():
def __init__(self, data=None, left=None, right=None):
self.data = data
self.left = left
self.right = right
# number of nodes for a perfect tree of the given height
def max_nodes_per_height(height: int) -> int:
return 2**(height + 1) - 1
def height_largest_complete_subtree(root: BTN) -> int:
CompleteInformation = namedtuple('CompleteInformation', ['height', 'num_nodes', 'max_height'])
def height_largest_complete_subtree_aux(root: BTN) -> CompleteInformation:
if (root is None):
return CompleteInformation(-1, 0, 0)
left_complete_info = height_largest_complete_subtree_aux(root.left)
right_complete_info = height_largest_complete_subtree_aux(root.right)
left_height = left_complete_info.height
right_height = right_complete_info.height
if (left_height == right_height):
if (left_complete_info.num_nodes == max_nodes_per_height(left_height)):
new_height = left_height + 1
new_num_nodes = left_complete_info.num_nodes + right_complete_info.num_nodes + 1
return CompleteInformation(new_height,
new_num_nodes,
max(new_height, max(left_complete_info.max_height, right_complete_info.max_height))
)
else:
new_height = left_height
new_num_nodes = max_nodes_per_height(left_height)
return CompleteInformation(new_height,
new_num_nodes,
max(new_height, max(left_complete_info.max_height, right_complete_info.max_height))
)
elif (left_height > right_height):
if (max_nodes_per_height(right_height) == right_complete_info.num_nodes):
new_height = right_height + 2
new_num_nodes = min(left_complete_info.num_nodes, max_nodes_per_height(right_height + 1)) + right_complete_info.num_nodes + 1
return CompleteInformation(new_height,
new_num_nodes,
max(new_height, max(left_complete_info.max_height, right_complete_info.max_height))
)
else:
new_height = right_height + 1
new_num_nodes = max_nodes_per_height(right_height) + right_complete_info.num_nodes + 1
return CompleteInformation(new_height,
new_num_nodes,
max(new_height, max(left_complete_info.max_height, right_complete_info.max_height))
)
elif (left_height < right_height):
if (left_complete_info.num_nodes == max_nodes_per_height(left_height)):
new_height = left_height + 1
new_num_nodes = left_complete_info.num_nodes + max_nodes_per_height(left_height) + 1
return CompleteInformation(new_height,
new_num_nodes,
max(new_height, max(left_complete_info.max_height, right_complete_info.max_height))
)
else:
new_height = left_height
new_num_nodes = (max_nodes_per_height(left_height - 1) * 2) + 1
return CompleteInformation(new_height,
new_num_nodes,
max(new_height, max(left_complete_info.max_height, right_complete_info.max_height))
)
return height_largest_complete_subtree_aux(root).max_height