问题描述
我成功地解决了这个问题,使用“天真的”解决方案检查每个节点的最长路径(包括该节点),但被告知有更好的解决方案。
我正在寻求有关如何有效解决此问题以及如何解决类似问题的帮助(建议或思考方法将不胜感激)
假设我有一棵树,其中每个节点都是橙色或白色。 我需要编写一个算法来获得最长的“好”路径的长度
“好”路径是从一个白色节点开始,向上爬上 0 个或更多白色节点,然后沿着 0 个或更多橙色节点向下走的路径
以下一棵树为例
算法应该返回 4,因为最长的路径从 18 开始,以 15 结束
解决方法
你可以用线性时间复杂度做到这一点:
按后序(深度优先)遍历树,对于每个访问过的节点,收集从该节点开始向下的最长单色路径的大小——因此该路径中的所有节点都应与当前节点具有相同的颜色.我们将此长度称为节点的“单色高度”
另外,如果当前节点是白色的,则获取其橙色子节点中最大的单色高度。如果当前(白色)单色高度和橙色高度的总和大于目前的最大值,则保留该总和作为最大化解决方案(迄今为止最好的)。
以下是实现该想法的 Python 代码:
class Node:
def __init__(self,data,colored=False,left=None,right=None):
self.data = data
self.colored = colored
self.left = left
self.right = right
def longestpath(root):
maxlen = 0
def monochromeheight(node): # recursive function
nonlocal maxlen # this is the overall best result
if node is None: # base case
return 0
# First get the children's data
leftheight = monochromeheight(node.left)
rightheight = monochromeheight(node.right)
# Then determine the monochrome height of this node
currheight = 0
if leftheight > 0 and node.left.colored == node.colored:
currheight = leftheight
if rightheight > currheight and node.right.colored == node.colored:
currheight = rightheight
currheight += 1
# Check whether this is a white node with an orange child.
# If so,check if the white + orange path form a better solution
if not node.colored:
if node.left and node.left.colored and currheight + leftheight > maxlen:
maxlen = currheight + leftheight
if node.right and node.right.colored and currheight + rightheight > maxlen:
maxlen = currheight + rightheight
return currheight
monochromeheight(root) # ignore returned value
return maxlen
然后在示例树上运行一个演示:
# Demo run on example tree
tree = Node(20,False,Node(18,Node(32,True,Node(70,Node(80,)
),Node(13,Node(17,True)
)
),Node(22,True)
),Node(26,None,Node(15,Node(30,Node(40,False),Node(25,True)
),Node(19,False)
)
)
)
print(longestpath(tree)) # 4