简体   繁体   English

有效地找到二叉树中最重的路径 - python

[英]Finding the heaviest path in a binary tree efficiently - python

I am trying to solve the following: finding the weight of the heaviest node in the tree and also representing that node as a list. 我试图解决以下问题:找到树中最重节点的权重,并将该节点表示为列表。 This is what I came up with, but I am pretty sure that it is a very messy solution. 这就是我想出来的,但我很确定这是一个非常混乱的解决方案。 Any advice on doing it more efficiently within the frame of the class given? 有关在课程框架内更有效地做到这一点的建议吗?

Given the class: 鉴于课程:

    class Tree_node():
        def __init__(self,key,val):
            self.key=key
            self.val=val
            self.left=None
            self.right=None  

    def __repr__(self):
    return "[" + str(self.left) + " " + str(self.key) + " " + \
                str(self.val) + " " + str(self.right) + "]"     

I calculate the weight of the heaviest path: 我计算最重的路径的重量:

def weight(node):
    if node == None:
        return 0
    if weight(node.left)>weight(node.right):
        return node.val+weight(node.left)
    else:
        return node.val+weight(node.right)

And then I try to return the heaviest path as a list: 然后我尝试将最重的路径作为列表返回:

def heavy_path(node):
    if node==None:
        return []
    elif node.val+weight(node.left)> node.val+weight(node.right):
        return [node.val] + filter_values(path_values(node.left))
    else:return [node.val] + filter_values(path_values(node.right))

def path_values(node):
    if node == None:
        return 0
    return [node.val,path_values(node.left),path_values(node.right)]

def filter_values (node):
    values = []
    sub_lists = []
    if node != 0:
        for value in node:
            if isinstance(value, list):
                sub_lists = filter_values(value)
            else:
                if value != 0:
                    values.append(value)
    return values+sub_lists

So that given a tree like [[None a 7 None] b 5 [[None c 8 None] d 3 None]]: 所以给定一个像[[无7无] b 5 [[无c 8无] d 3无]]的树:

>>> weight(t)
16
>>> heavy_path(t)
[5, 3, 8]

What would be a better way of doing this? 这会是一个更好的方法吗?

Assuming that you are interpreting the heaviest path as being a path that always begins with the root of the tree and descends down to a single leaf. 假设您将最重的路径解释为始终以树的根开始并下降到单个叶的路径。 You could try merging the weight-finding and path-building operations: 您可以尝试合并重量查找和路径构建操作:

def heavy_path(node):
  if not node
    return (0,[])
  [lweight,llist] = heavy_path(node.left)
  [rweight,rlist] = heavy_path(node.right)
  if lweight>rweight:
    return (node.val+lweight,[node.val]+llist)
  else:
    return (node.val+rweight,[node.val]+rlist)

Or using a time-honoured technique to speed up this kind of calculation through Memoization . 或者使用历史悠久的技术通过Memoization加速这种计算。 Once you've used memoization once, you could just keep the pathweight values up to date as you alter your tree. 一旦使用了memoization,就可以在更改树时保持路径权值最新。

def weight(node):
  if node == None:
      return 0
  node.pathweight=node.val+max(weight(node.left),weight(node.right))
  return node.pathweight

def heavy_edge(node):
  if not node.left:
    lweight=0
  else:
    lweight=node.left.pathweight
  if not node.right:
    rweight=0
  else:
    rweight=node.right.pathweight
  if lweight>rweight:
    return [node.val,heavy_edge(node.left)]
  else:
    return [node.val,heavy_edge(node.right)]

weight(t) #Precalculate the pathweight of all the nodes in O(n) time
heavy_edge(T) #Use the precalculated pathweights to efficient find list the heaviest path in O(lg n) time

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM