Given an undirected graph(with no cycles) represented using an adjacency list adj[][], find the diameter of the graph. The diameter of a graph (sometimes called the width) is the number of edges on the longest path between two nodes in the graph.
Note: Graph do not contain any disconnected component.
[Approach - 1] Finding farthest node from each node - O(n2) Time and O(n) Space
This approach considers every node as a starting point and finds its farthest reachable node. This way, we cover all possibilities of taking each node as the endpoint of the diameter.
C++
//Driver Code Starts#include<vector>#include<iostream>usingnamespacestd;//Driver Code EndsintfarthestNode(intcurr,vector<bool>&visited,vector<vector<int>>&adj,intdist){if(visited[curr])return0;visited[curr]=true;intmaxDist=dist;for(intnext:adj[curr]){// visiting the next node // if not visited alreadyif(!visited[next]){maxDist=max(maxDist,farthestNode(next,visited,adj,dist+1));}}returnmaxDist;}intdiameter(vector<vector<int>>&adj){intn=adj.size();intres=0;// taking maximum across all nodesfor(inti=0;i<n;i++){vector<bool>visited(n,false);res=max(res,farthestNode(i,visited,adj,0));}returnres;}//Driver Code StartsvoidaddEdge(vector<vector<int>>&adj,intu,intv){adj[u].push_back(v);adj[v].push_back(u);}intmain(){intV=5;vector<vector<int>>adj(V);// creating adjacency listaddEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);intres=diameter(adj);cout<<res<<endl;return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;classGFG{//Driver Code Endsstaticintdiameter(ArrayList<ArrayList<Integer>>adj){intn=adj.size();intres=0;// taking maximum across all nodesfor(inti=0;i<n;i++){boolean[]visited=newboolean[n];res=Math.max(res,farthestNode(i,visited,adj,0));}returnres;}staticintfarthestNode(intcurr,boolean[]visited,ArrayList<ArrayList<Integer>>adj,intdist){if(visited[curr])return0;visited[curr]=true;intmaxDist=dist;for(intnext:adj.get(curr)){// visiting the next node // if not visited alreadyif(!visited[next]){maxDist=Math.max(maxDist,farthestNode(next,visited,adj,dist+1));}}returnmaxDist;}//Driver Code StartsstaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,intu,intv){adj.get(u).add(v);adj.get(v).add(u);}publicstaticvoidmain(String[]args){intV=5;ArrayList<ArrayList<Integer>>adj=newArrayList<>();// creating adjacency listfor(inti=0;i<V;i++)adj.add(newArrayList<>());addEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);intres=diameter(adj);System.out.println(res);}}//Driver Code Ends
Python
deffarthestNode(curr,visited,adj,dist):ifvisited[curr]:return0visited[curr]=TruemaxDist=distfornext_nodeinadj[curr]:# visiting the next node # if not visited alreadyifnotvisited[next_node]:maxDist=max(maxDist,farthestNode(next_node,visited,adj,dist+1))returnmaxDistdefdiameter(adj):n=len(adj)res=0# taking maximum across all nodesforiinrange(n):visited=[False]*nres=max(res,farthestNode(i,visited,adj,0))returnres#Driver Code StartsdefaddEdge(adj,u,v):adj[u].append(v)adj[v].append(u)if__name__=="__main__":V=5adj=[]# creating adjacency listforiinrange(V):adj.append([])addEdge(adj,0,1)addEdge(adj,1,2)addEdge(adj,2,3)addEdge(adj,3,4)res=diameter(adj)print(res)#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGFG{//Driver Code EndsstaticintfarthestNode(intcurr,bool[]visited,List<List<int>>adj,intdist){if(visited[curr])return0;visited[curr]=true;intmaxDist=dist;foreach(intnextinadj[curr]){// visiting the next node // if not visited alreadyif(!visited[next]){maxDist=Math.Max(maxDist,farthestNode(next,visited,adj,dist+1));}}returnmaxDist;}staticintdiameter(List<List<int>>adj){intn=adj.Count;intres=0;// taking maximum across all nodesfor(inti=0;i<n;i++){bool[]visited=newbool[n];res=Math.Max(res,farthestNode(i,visited,adj,0));}returnres;}//Driver Code StartsstaticvoidaddEdge(List<List<int>>adj,intu,intv){adj[u].Add(v);adj[v].Add(u);}staticvoidMain(){intV=5;List<List<int>>adj=newList<List<int>>();// creating adjacency listfor(inti=0;i<V;i++)adj.Add(newList<int>());addEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);intres=diameter(adj);Console.WriteLine(res);}}//Driver Code Ends
JavaScript
functionfarthestNode(curr,visited,adj,dist){if(visited[curr])return0;visited[curr]=true;letmaxDist=dist;for(constnextofadj[curr]){// visiting the next node // if not visited alreadyif(!visited[next]){maxDist=Math.max(maxDist,farthestNode(next,visited,adj,dist+1));}}returnmaxDist;}functiondiameter(adj){constn=adj.length;letres=0;// taking maximum across all nodesfor(leti=0;i<n;i++){letvisited=Array(n).fill(false);res=Math.max(res,farthestNode(i,visited,adj,0));}returnres;}//Driver Code StartsfunctionaddEdge(adj,u,v){adj[u].push(v);adj[v].push(u);}// Driver codeletV=5;letadj=[];// creating adjacency listfor(leti=0;i<V;i++)adj.push([]);addEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);constres=diameter(adj);console.log(res);//Driver Code Ends
Output
4
[Expected Approach-1] Finding ends of diameter - O(n) Time and O(n) Space
In this approach, we first perform a DFS (or BFS) from any node to find the farthest node, which becomes one endpoint of the longest path. Then, starting from this farthest node, we perform another DFS to find the node farthest from it. The distance between these two nodes gives the tree’s diameter, representing the longest path between any two nodes.
Why this approach works?
This works because in a tree, the longest path (diameter) always has its endpoints as the farthest nodes from each other. When we run the first DFS from any node, we reach one endpoint of this longest path. Running the second DFS from that endpoint ensures we traverse the maximum possible distance in the tree, therefore, discovering the diameter.
C++
//Driver Code Starts#include<vector>#include<iostream>usingnamespacestd;//Driver Code EndsvoidfarthestNode(intcurr,vector<vector<int>>&adj,intcurrentDist,vector<int>&dist,vector<bool>&visited){if(visited[curr])return;if(dist[0]<currentDist){// contains an array with index 0// having max dist and index 1 having// node at that distance from srcdist[0]=currentDist;dist[1]=curr;}visited[curr]=true;for(intnext:adj[curr]){if(!visited[next]){farthestNode(next,adj,currentDist+1,dist,visited);}}}intdiameter(vector<vector<int>>&adj){intn=adj.size();vector<int>dist={0,0};vector<bool>visited(n+1,false);// finding node at max distance from 0th nodefarthestNode(0,adj,0,dist,visited);intend1=dist[1];dist={0,0};// finding node at max distance // from end1 of diametervector<bool>visited2(n,false);farthestNode(end1,adj,0,dist,visited2);returndist[0];}//Driver Code StartsvoidaddEdge(vector<vector<int>>&adj,intu,intv){adj[u].push_back(v);adj[v].push_back(u);}intmain(){intV=5;vector<vector<int>>adj(V);// creating adjacency listaddEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);intres=diameter(adj);cout<<res<<endl;return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;classGFG{//Driver Code Endsstaticintdiameter(ArrayList<ArrayList<Integer>>adj){intn=adj.size();int[]dist=newint[2];// finding node at max distance from 0th nodefarthestNode(0,adj,0,dist,newboolean[n]);intend1=dist[1];dist=newint[2];// finding node at max distance // from end1 of diameterfarthestNode(end1,adj,0,dist,newboolean[n]);returndist[0];}staticvoidfarthestNode(intcurr,ArrayList<ArrayList<Integer>>adj,intcurrentDist,int[]dist,boolean[]visited){if(visited[curr])return;if(dist[0]<currentDist){// contains an array with index 0// having max dist and index 1 having// node at that distance from srcdist[0]=currentDist;dist[1]=curr;}visited[curr]=true;for(intnext:adj.get(curr)){if(!visited[next]){farthestNode(next,adj,currentDist+1,dist,visited);}}}//Driver Code StartsstaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,intu,intv){adj.get(u).add(v);adj.get(v).add(u);}publicstaticvoidmain(String[]args){intV=5;ArrayList<ArrayList<Integer>>adj=newArrayList<>();// creating adjacency listfor(inti=0;i<V;i++)adj.add(newArrayList<>());addEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);intres=diameter(adj);System.out.println(res);}}//Driver Code Ends
Python
deffarthestNode(curr,adj,currentDist,dist,visited):ifvisited[curr]:returnifdist[0]<currentDist:# contains an array with index 0# having max dist and index 1 having# node at that distance from srcdist[0]=currentDistdist[1]=currvisited[curr]=Truefornext_nodeinadj[curr]:ifnotvisited[next_node]:farthestNode(next_node,adj,currentDist+1,dist,visited)defdiameter(adj):n=len(adj)+1dist=[0,0]# finding node at max distance from 0th nodefarthestNode(0,adj,0,dist,[False]*n)end1=dist[1]dist=[0,0]# finding node at max distance # from end1 of diameterfarthestNode(end1,adj,0,dist,[False]*n)returndist[0]#Driver Code StartsdefaddEdge(adj,u,v):adj[u].append(v)adj[v].append(u)if__name__=="__main__":V=5adj=[]# creating adjacency listforiinrange(V):adj.append([])addEdge(adj,0,1)addEdge(adj,1,2)addEdge(adj,2,3)addEdge(adj,3,4)res=diameter(adj)print(res)#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGFG{//Driver Code EndsstaticvoidfarthestNode(intcurr,List<List<int>>adj,intcurrentDist,int[]dist,bool[]visited){if(visited[curr])return;if(dist[0]<currentDist){// contains an array with index 0// having max dist and index 1 having// node at that distance from srcdist[0]=currentDist;dist[1]=curr;}visited[curr]=true;foreach(intnextinadj[curr]){if(!visited[next]){farthestNode(next,adj,currentDist+1,dist,visited);}}}staticintdiameter(List<List<int>>adj){intn=adj.Count;int[]dist=newint[2];// finding node at max distance from 0th nodefarthestNode(0,adj,0,dist,newbool[n+1]);intend1=dist[1];dist=newint[2];// finding node at max distance // from end1 of diameterfarthestNode(end1,adj,0,dist,newbool[n]);returndist[0];}//Driver Code StartsstaticvoidaddEdge(List<List<int>>adj,intu,intv){adj[u].Add(v);adj[v].Add(u);}staticvoidMain(){intV=5;List<List<int>>adj=newList<List<int>>();// creating adjacency listfor(inti=0;i<V;i++)adj.Add(newList<int>());addEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);intres=diameter(adj);Console.WriteLine(res);}}//Driver Code Ends
JavaScript
functionfarthestNode(curr,adj,currentDist,dist,visited){if(visited[curr])return;if(dist[0]<currentDist){// contains an array with index 0// having max dist and index 1 having// node at that distance from srcdist[0]=currentDist;dist[1]=curr;}visited[curr]=true;for(constnextofadj[curr]){if(!visited[next]){farthestNode(next,adj,currentDist+1,dist,visited);}}}functiondiameter(adj){constn=adj.length+1;letdist=[0,0];// finding node at max distance from 0th nodefarthestNode(0,adj,0,dist,Array(n).fill(false));constend1=dist[1];dist=[0,0];// finding node at max distance // from end1 of diameterfarthestNode(end1,adj,0,dist,Array(n).fill(false));returndist[0];}//Driver Code StartsfunctionaddEdge(adj,u,v){adj[u].push(v);adj[v].push(u);}// Driver codeletV=5;letadj=[];// creating adjacency listfor(leti=0;i<V;i++)adj.push([]);addEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);constres=diameter(adj);console.log(res);//Driver Code Ends
Output
4
[Expected Approach-2] Taking each node as Meeting point- O(n) Time and O(n) Space
In this approach, we compute the diameter by considering each node as a potential meeting point of the longest path. For each node, we find the two farthest leaf nodes (in terms of distance) within its reachable subgraph. The sum of their distances (plus the two connecting edges through the current node) gives a candidate diameter passing through that node. The maximum of these candidate values across all nodes yields the actual diameter of the graph.
How to compute diameter from each meeting point?
The diameter is found by recursively computing the height of each node based on its children.
For every node, its height is determined as 1 + the maximum height among its child nodes.
If the node is a leaf, its height is 0.
While computing heights, we track the longest path passing through each node.
This path is calculated by summing the two largest child heights and adding two edges that connect them through the current node.
The maximum such path length across all nodes gives the overall diameter of the tree.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;//Driver Code EndsvoiddfsPrune(intcurr,vector<vector<int>>&adj,vector<bool>&visited){if(visited[curr])return;visited[curr]=true;for(intnext:adj[curr]){// remove back edge to make it a rooted treeautoit=find(adj[next].begin(),adj[next].end(),curr);if(it!=adj[next].end())adj[next].erase(it);dfsPrune(next,adj,visited);}}intfindHeight(intcurr,vector<vector<int>>&adj,vector<int>&height){if(height[curr]!=-1)returnheight[curr];// leaf node has height = 0inttemp=0;for(intnext:adj[curr]){temp=max(temp,1+findHeight(next,adj,height));}returnheight[curr]=temp;}intdiameter(vector<vector<int>>&adj){intn=adj.size();vector<bool>visited(n,false);vector<int>height(n,-1);// root the tree at 0dfsPrune(0,adj,visited);fill(visited.begin(),visited.end(),false);findHeight(0,adj,height);intres=0;for(inti=0;i<n;i++){intfirstMax=-1,secondMax=-1;for(intnext:adj[i]){inthVal=height[next];if(hVal>firstMax){secondMax=firstMax;firstMax=hVal;}elseif(hVal>secondMax){secondMax=hVal;}}// take 2 children with max distance from root = iif(firstMax!=-1&&secondMax!=-1)res=max(res,2+firstMax+secondMax);elseif(firstMax!=-1)res=max(res,1+firstMax);}returnres;}//Driver Code StartsvoidaddEdge(vector<vector<int>>&adj,intu,intv){adj[u].push_back(v);adj[v].push_back(u);}intmain(){intV=5;vector<vector<int>>adj(V);// creating adjacency listfor(inti=0;i<V;i++)adj[i]=vector<int>();addEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);intres=diameter(adj);cout<<res<<endl;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.Arrays;importjava.util.ArrayList;classGFG{//Driver Code EndsstaticvoiddfsPrune(intcurr,ArrayList<ArrayList<Integer>>adj,boolean[]visited){if(visited[curr])return;visited[curr]=true;for(intnext:adj.get(curr)){// remove back edge to make it a rooted treeadj.get(next).remove(Integer.valueOf(curr));dfsPrune(next,adj,visited);}}staticintfindHeight(intcurr,ArrayList<ArrayList<Integer>>adj,int[]height){if(height[curr]!=-1)returnheight[curr];// leaf node has height = 0inttemp=0;for(intnext:adj.get(curr)){temp=Math.max(temp,1+findHeight(next,adj,height));}returnheight[curr]=temp;}staticintdiameter(ArrayList<ArrayList<Integer>>adj){intn=adj.size();boolean[]visited=newboolean[n];int[]height=newint[n];Arrays.fill(height,-1);// root the tree at 0dfsPrune(0,adj,visited);Arrays.fill(visited,false);findHeight(0,adj,height);intres=0;for(inti=0;i<n;i++){intfirstMax=-1,secondMax=-1;for(intnext:adj.get(i)){inthVal=height[next];if(hVal>firstMax){secondMax=firstMax;firstMax=hVal;}elseif(hVal>secondMax){secondMax=hVal;}}// take 2 children with max distance from root = iif(firstMax!=-1&&secondMax!=-1)res=Math.max(res,2+firstMax+secondMax);elseif(firstMax!=-1)res=Math.max(res,1+firstMax);}returnres;}//Driver Code StartsstaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,intu,intv){adj.get(u).add(v);adj.get(v).add(u);}publicstaticvoidmain(String[]args){intV=5;ArrayList<ArrayList<Integer>>adj=newArrayList<>();// creating adjacency listfor(inti=0;i<V;i++)adj.add(newArrayList<>());addEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);intres=diameter(adj);System.out.println(res);}}//Driver Code Ends
Python
defdfsPrune(curr,adj,visited):ifvisited[curr]:returnvisited[curr]=Truefornextinadj[curr]:# remove back edge to make it a rooted treeadj[next].remove(curr)dfsPrune(next,adj,visited)deffindHeight(curr,adj,height):ifheight[curr]!=-1:returnheight[curr]# leaf node has height = 0temp=0fornext_nodeinadj[curr]:temp=max(temp,1+findHeight(next_node,adj,height))height[curr]=tempreturnheight[curr]defdiameter(adj):n=len(adj)visited=[False]*nheight=[-1]*n# root the tree at 0dfsPrune(0,adj,visited)visited=[False]*nfindHeight(0,adj,height)res=0foriinrange(n):firstMax=-1secondMax=-1fornextinadj[i]:hVal=height[next]ifhVal>firstMax:secondMax=firstMaxfirstMax=hValelifhVal>secondMax:secondMax=hVal# take 2 children with max distance from root = iiffirstMax!=-1andsecondMax!=-1:res=max(res,2+firstMax+secondMax)eliffirstMax!=-1:res=max(res,1+firstMax)returnres#Driver Code StartsdefaddEdge(adj,u,v):adj[u].append(v)adj[v].append(u)if__name__=="__main__":V=5adj=[]# creating adjacency listforiinrange(V):adj.append([])addEdge(adj,0,1)addEdge(adj,1,2)addEdge(adj,2,3)addEdge(adj,3,4)res=diameter(adj)print(res)#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;usingSystem.Linq;classGFG{//Driver Code EndsstaticvoiddfsPrune(intcurr,List<List<int>>adj,bool[]visited){if(visited[curr])return;visited[curr]=true;foreach(intnextinadj[curr]){// remove back edge to make it a rooted treeadj[next].Remove(curr);dfsPrune(next,adj,visited);}}staticintfindHeight(intcurr,List<List<int>>adj,int[]height){if(height[curr]!=-1)returnheight[curr];// leaf node has height = 0inttemp=0;foreach(intnextinadj[curr]){temp=Math.Max(temp,1+findHeight(next,adj,height));}returnheight[curr]=temp;}staticintdiameter(List<List<int>>adj){intn=adj.Count;bool[]visited=newbool[n];int[]height=Enumerable.Repeat(-1,n).ToArray();// root the tree at 0dfsPrune(0,adj,visited);Array.Fill(visited,false);findHeight(0,adj,height);intres=0;for(inti=0;i<n;i++){intfirstMax=-1,secondMax=-1;foreach(intnextinadj[i]){inthVal=height[next];if(hVal>firstMax){secondMax=firstMax;firstMax=hVal;}elseif(hVal>secondMax){secondMax=hVal;}}// take 2 children with max distance from root = iif(firstMax!=-1&&secondMax!=-1)res=Math.Max(res,2+firstMax+secondMax);elseif(firstMax!=-1)res=Math.Max(res,1+firstMax);}returnres;}//Driver Code StartsstaticvoidaddEdge(List<List<int>>adj,intu,intv){adj[u].Add(v);adj[v].Add(u);}staticvoidMain(){intV=5;List<List<int>>adj=newList<List<int>>();// creating adjacency listfor(inti=0;i<V;i++)adj.Add(newList<int>());addEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);intres=diameter(adj);Console.WriteLine(res);}}//Driver Code Ends
JavaScript
functiondfsPrune(curr,adj,visited){if(visited[curr])return;visited[curr]=true;for(letnextofadj[curr]){// remove back edge to make it a rooted treeadj[next]=adj[next].filter(x=>x!==curr);dfsPrune(next,adj,visited);}}functionfindHeight(curr,adj,height){if(height[curr]!==-1)returnheight[curr];// leaf node has height = 0lettemp=0;for(letnextofadj[curr]){temp=Math.max(temp,1+findHeight(next,adj,height));}height[curr]=temp;returnheight[curr];}functiondiameter(adj){constn=adj.length;letvisited=Array(n).fill(false);letheight=Array(n).fill(-1);// root the tree at 0dfsPrune(0,adj,visited);visited.fill(false);findHeight(0,adj,height);letres=0;for(leti=0;i<n;i++){letfirstMax=-1,secondMax=-1;for(letnextofadj[i]){lethVal=height[next];if(hVal>firstMax){secondMax=firstMax;firstMax=hVal;}elseif(hVal>secondMax){secondMax=hVal;}}// take 2 children with max distance from root = iif(firstMax!==-1&&secondMax!==-1)res=Math.max(res,2+firstMax+secondMax);elseif(firstMax!==-1)res=Math.max(res,1+firstMax);}returnres;}//Driver Code StartsfunctionaddEdge(adj,u,v){adj[u].push(v);adj[v].push(u);}// Driver codeletV=5;letadj=[];// creating adjacency listfor(leti=0;i<V;i++)adj.push([]);addEdge(adj,0,1);addEdge(adj,1,2);addEdge(adj,2,3);addEdge(adj,3,4);constres=diameter(adj);console.log(res);//Driver Code Ends