题解 | #树的直径#

树的直径

http://www.nowcoder.com/practice/a77b4f3d84bf4a7891519ffee9376df3

本题最大的麻烦之处在于输入是离散的一条条边,没有直接保存节点,需要从这些边当中提取节点的信息,从而将他们处理成树的关系,即:要保存节点,以及节点之间的边长

由于不是二叉树,每个节点的子节点可能存在多个,则需要用一个二维的结构来保存树。

然后再使用“二叉树中的最大路径和”的结题思路,采取动态规划算法即可。

这里我是用了字典结构,键是起始节点,值是终止节点,遍历一次可以得到每个节点到其他节点的关系。为了避免输入有向性造成树的构建不完整,因此每个节点都单独保存,在递归计算的时候把上级节点序号传入,用来避免原路返回,以题中的样例,即:

{
	0:[1],
	1:[0,2,5],
	2:[1,3,4],
    3:[2],
    4:[2],
    5:[1]
}

空间复杂度是O(2n-2)=>O(n),时间复杂度是遍历全树的时间O(n),具体代码如下:

global maxlen,graph,graph_value
maxlen=float('-inf')
def walk(startnode,prenode):
    global maxlen,graph,graph_value
    if len(graph[startnode])==1 and graph[startnode][0]==prenode:
        return float('-inf')#1.只是求最大路径和,则端点返回最大路径是负无穷
        #return 0#2. 如果是必须经过,则端点返回最大路径0

    singleMax=[]#保存不同下级节点经过本级节点时最大路径
    for i in range(len(graph[startnode])):
        endnode=graph[startnode][i]
        if endnode==prenode:#忽略上级来的节点,只往下走
            continue
        maxtmp=max(graph_value[startnode][i]+walk(endnode,startnode),graph_value[startnode][i])#1.只是求最大路径和,可以不要下级的数据
        #maxtmp=graph_value[startnode][i]+walk(endnode,startnode)#2. 如果是必须经过,则不能不要下级节点的数据
        singleMax.append(maxtmp)
    singleMax.sort(reverse=True)
    if len(singleMax)==1:#只有一个下级节点时
        maxlen=max(maxlen,singleMax[0])
    elif len(singleMax)>1:#多个下级节点时,最大的两边组成最长路径
        maxlen=max(maxlen,singleMax[0]+singleMax[1])
    return singleMax[0]#向上返回过当前节点的最大路径
                
class Solution:
    def solve(self , n: int, Tree_edge: List[Interval], Edge_value: List[int]) -> int:
        # write code here
        global maxlen,graph,graph_value
        if n<=1:
            return 0
        if n==2:
            return Edge_value[0]
        else:
            graph={}
            graph_value={}
            for i in range(len(Tree_edge)):#保存每个节点到其他节点的边,以及边长
                edge=Tree_edge[i]
                if edge.start not in graph:
                    graph[edge.start]=[]
                    graph_value[edge.start]=[]
                if edge.end not in graph:
                    graph[edge.end]=[]
                    graph_value[edge.end]=[]
                graph[edge.start].append(edge.end)
                graph[edge.end].append(edge.start)
                graph_value[edge.start].append(Edge_value[i])
                graph_value[edge.end].append(Edge_value[i])
        
        for startnode in graph:
            if len(graph[startnode])==1:#取一个末端端点作为起点,或者随意找一个点均可
                break

        global maxlen
        walk(startnode,'-1')#初始节点没有上级节点
        return maxlen
     


全部评论
感谢大佬
点赞 回复 分享
发布于 2022-03-13 23:11

相关推荐

昨天 11:19
已编辑
门头沟学院 Java
已经一年没发牛客了,为什么呢,因为没脸发...&nbsp;一年前的我自认为在25届中技术一流,八股无敌,项目出色,但是一年校招的蹉跎让我差点转行。24年春招收割了十几个实习&nbsp;offer&nbsp;之后我去了某家大厂实习到9月份转正失败,那时候的我还没有意识到噩梦将来,7月因为投秋招提前批没反馈,于是开始投了几个实习转正岗位练手又拿了3个中大厂&nbsp;offer,这时的我沉浸在我自以为是的骄傲里。9月秋招正式批开始后我几乎把我能找到的所有的岗位都投了一遍,只收获了大厂海笔,0面试。10月份第一家给我面试的公司是数字马力(蚂蚁的内包),诚恳的说,当时收到这家面试是嚣张的,觉得我拿这个&nbsp;offer&nbsp;如探囊取物,就当个保底吧。...
中街牛奶提子:是啊,不应该在秋招的时候继续投实习岗。也劝26届的,八月末后,实习岗就不应该投,给人错误的行情认知。佬是学院本,觉得约面难,双非何尝不是一样呢,秋招战场的激烈和实习完全不同。当时我秋招的时候也是边面实习,当时面实习面一个过一个觉得自己很优越,觉得能收获一堆实习offer那秋招肯定也行。为什么要在秋招拿一堆实习offer增强自己所谓的虚荣心,当时就是贱,为了所谓的攀比虚荣心
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客企业服务