Hello I solved this leetcode https://leetcode.com/problems/tree-diameter/ question reserved for people who pay the subscription.
The question:
Given an undirected tree (tree is not disjoint), return its diameter: the number of edges in a longest path in that tree.
The tree is given as an array of edges where edges[i] = [u, v] is a bidirectional edge between nodes u and v. Each node has labels in the set {0, 1, ..., edges.length}.
So the "easy" way to solve it is to start a dfs at each node in the tree and keep track of the longest path seen so far, which would be O(n^2)
. Given n = number of vertexes
in the graph.
However I came up with the below solution that does the job in O(n)
, I was able to come up with it by going through examples on a piece of paper and then coded it and it passed all the tests, but I can't figure out why it formally works, can anyone help me prove it is correct ?
Here is my code:
def treeDiameter(self, edges: List[List[int]]) -> int:
def dfs(graph, vertex, prev, maximums):
for neighboor in graph[vertex]:
if neighboor != prev:
tmp = 1 + dfs(graph, neighboor, vertex, maximums)
if tmp > maximums[vertex][0]:
maximums[vertex][1] = maximums[vertex][0]
maximums[vertex][0] = tmp
elif tmp > maximums[vertex][1]:
maximums[vertex][1] = tmp
return maximums[vertex][0]
graph = collections.defaultdict(list)
for vertex1, vertex2 in edges:
graph[vertex1].append(vertex2)
graph[vertex2].append(vertex1)
maximums = [[0, 0] for _ in range(len(edges) + 1)]
dfs(graph, 0, None, maximums)
res = 0
for max1, max2 in maximums:
res = max(res, max1 + max2)
return res
The way I came up with this is I realized if I start my dfs at a node that is on the longest path, then the longest path is equal to the sum of the two longest pathes (because it is a tree there are no cycles) out of this node (which is why I store the two longest pathes max1, max2
out of a node in the maximums
array) --> but what I fail to see is why that works in all cases.