
Problem Statement
In this problem, you are presented with a unique type of directed graph described by n
nodes, where nodes are indexed from 0
to n-1
. Each node is connected via a directed edge to at most one other node, as specified by an array edges
. The array edges
is 0-indexed where an element at index i
gives the destination node of a directed edge from node i
. If an element is -1
, it indicates that the node at that index has no outgoing edges.
Given this graph setup and two specific nodes, node1
and node2
, your task is to determine the index of a node that can be reached from both node1
and node2
such that the maximum distance to reach this node from either of the starting nodes is as small as possible. If multiple such nodes exist, the node with the smallest index should be returned. If it is not possible to find such a node, return -1
. Note that the graph can have cycles, which may influence reaching a node and the computation of distances.
Examples
Example 1
Input:
edges = [2,2,3,-1], node1 = 0, node2 = 1
Output:
2
Explanation:
The distance from node 0 to node 2 is 1, and the distance from node 1 to node 2 is 1. The maximum of those two distances is 1. It can be proven that we cannot get a node with a smaller maximum distance than 1, so we return node 2.
Example 2
Input:
edges = [1,2,-1], node1 = 0, node2 = 2
Output:
2
Explanation:
The distance from node 0 to node 2 is 2, and the distance from node 2 to itself is 0. The maximum of those two distances is 2. It can be proven that we cannot get a node with a smaller maximum distance than 2, so we return node 2.
Constraints
n == edges.length
2 <= n <= 105
-1 <= edges[i] < n
edges[i] != i
0 <= node1, node2 < n
Approach and Intuition
When approaching this problem, a good understanding of graph traversal and shortest path algorithms is essential, as well as handling special cases involving directed cyclic graphs. Here’s a step-by-step breakdown of how we can approach finding the solution:
Understand and visualize traveling from
node1
andnode2
. Since each node leads to at most one other node:- Travel involves following a singular path until you reach a terminal node or cycle back to a previously visited node.
Compute reachable nodes along with their distances from both
node1
andnode2
:- Start at
node1
and keep track of each node visited and the distance taken to reach it until you hit a node that either cycles or has no outgoing edges. - Repeat the process starting at
node2
.
- Start at
Identify nodes that can be reached from both
node1
andnode2
:- Compare the sets of visited nodes from both starting points.
- For nodes present in both sets, compute the maximum of the distances from the two starting nodes to these common nodes.
Find the optimal node:
- From the set of commonly reachable nodes, select the node with the smallest maximum distance.
- If there are ties (multiple nodes with the same maximum distance), return the one with the smallest index.
- If no common nodes are found, return
-1
.
This approach leverages straightforward graph traversal while keeping track of distances, making it efficient yet simple to implement given the graph’s constrained structure where each node links to at most one other node.
Solutions
- C++
- Java
class Solution {
public:
void exploreGraph(int current, vector<int>& connections, vector<int>& distance, vector<bool>& visited) {
visited[current] = true;
int next = connections[current];
if (next != -1 && !visited[next]) {
distance[next] = 1 + distance[current];
exploreGraph(next, connections, distance, visited);
}
}
int findClosestNode(vector<int>& connections, int start1, int start2) {
int sz = connections.size();
vector<int> distance1(sz, numeric_limits<int>::max()), distance2(sz, numeric_limits<int>::max());
vector<bool> seen1(sz), seen2(sz);
distance1[start1] = 0, distance2[start2] = 0;
exploreGraph(start1, connections, distance1, seen1);
exploreGraph(start2, connections, distance2, seen2);
int closestNode = -1, minimumDistance = numeric_limits<int>::max();
for (int i = 0; i < sz; i++) {
if (minimumDistance > max(distance1[i], distance2[i])) {
closestNode = i;
minimumDistance = max(distance1[i], distance2[i]);
}
}
return closestNode;
}
};
This C++ solution efficiently identifies the closest node to two given nodes in a directed graph represented as a list of connections, where each index and its value portray a directional connection from index to value.
- Initiate by defining the
exploreGraph
function to explore the graph and compute the distance from the starting node to all other nodes using simple DFS. This function updates thedistance
array with the number of steps taken to reach each node and uses avisited
array to keep track of explored nodes. - Proceed to define the
findClosestNode
function:- Prepare two distance vectors
distance1
anddistance2
, initializing them with maximum integer values. These arrays will store the minimal distances from the two start nodes defined bystart1
andstart2
. - Two boolean vectors
seen1
andseen2
are used to record if a node has been visited starting fromstart1
andstart2
. - Call
exploreGraph
for both start nodes to fill out thedistance1
anddistance2
arrays. - Initialize
closestNode
to -1 to indicate that no node has been found initially. Iterate over all nodes. For each node, determine the greater of the two distances (max(distance1[i], distance2[i])
). Update theclosestNode
with the node index if this maximum is less than the previously recorded minimum distance. - Eventually, return the
closestNode
which represents the node that has the shortest largest distance to both start nodes.
- Prepare two distance vectors
This implementation excels in clarity and scalability, effectively capturing both single-path distances and identifying optimal node accessibility in the context of varying graph topologies.
class GraphTraversal {
public void depthFirstSearch(int vertex, int[] connections, int[] pathLength, Boolean[] visited) {
visited[vertex] = true;
int next = connections[vertex];
if (next != -1 && !visited[next]) {
pathLength[next] = pathLength[vertex] + 1;
depthFirstSearch(next, connections, pathLength, visited);
}
}
public int findClosestNode(int[] connections, int start1, int start2) {
int totalVertices = connections.length;
int[] path1 = new int[totalVertices], path2 = new int[totalVertices];
Arrays.fill(path1, Integer.MAX_VALUE);
Arrays.fill(path2, Integer.MAX_VALUE);
path1[start1] = 0;
path2[start2] = 0;
Boolean[] visited1 = new Boolean[totalVertices], visited2 = new Boolean[totalVertices];
Arrays.fill(visited1, Boolean.FALSE);
Arrays.fill(visited2, Boolean.FALSE);
depthFirstSearch(start1, connections, path1, visited1);
depthFirstSearch(start2, connections, path2, visited2);
int minIndex = -1, minDistance = Integer.MAX_VALUE;
for (int i = 0; i < totalVertices; i++) {
if (minDistance > Math.max(path1[i], path2[i])) {
minIndex = i;
minDistance = Math.max(path1[i], path2[i]);
}
}
return minIndex;
}
}
This Java program helps find the closest node between two given nodes within a graph represented by an adjacency list. The solution utilizes a Depth-First Search (DFS) approach to determine the shortest path lengths from each starting node to all other nodes in the graph. Here’s how the provided solution operates:
DepthFirstSearch Method:
- Initialize each traversal with the start vertex marked as visited.
- Explore all connected vertices recursively.
- Keep tracking the path length from the start vertex to the current vertex, updating the shortest path found.
FindClosestNode Method:
- Set up initial conditions, marking path lengths from the start nodes to infinite (except to themselves where it's 0) and marking all nodes as unvisited.
- Conduct individual depth-first searches starting from each of the two given nodes.
- Post DFS, evaluate each vertex in the graph to find the vertex that has the smallest maximum distance from either start node.
The outcome is an integer representing the index of the closest node to the two given start nodes, minimizing the longest path from either start node. This solution efficiently maps out paths to determine the most centrally located vertex relative to the two specified starting nodes, leveraging DFS to handle potentially complex connection scenarios in the graph.
No comments yet.