0% completed
Problem Statement
You have a directed graph with n
nodes labeled from 0
to n-1
. The graph has two types of edges: red and blue. You are given two arrays redEdges
and blueEdges
:
redEdges[i] = [ai, bi]
means there's a red edge from nodeai
to nodebi
.blueEdges[j] = [uj, vj]
means there's a blue edge from nodeuj
to nodevj
.
Find the shortest path from node 0
to each node x
such that the edges alternate in colors. If there is no such path, return -1
for that node.
Return an array answer
of length n
, where answer[x]
is the length of the shortest alternating path from node 0
to node x
.
Examples
Example 1:
- Input: n = 4, redEdges = [[0, 1], [1, 2], [2, 3]], blueEdges = [[0, 2], [2, 1], [1, 3]]
- Expected Output: [0, 1, 1, 2]
- Justification:
- Node
0
is the start, so distance is0
. - Shortest path to node
1
is directly from0
using red edge. - Shortest path to node
2
is directly from0
using blue edge. - Shortest path to node
3
is via node1
using red then blue edge.
- Node
Example 2:
- Input: n = 3, redEdges = [[0, 1]], blueEdges = [[2, 1]]
- Expected Output: [0, 1, -1]
- Justification:
- Node
0
is the start, so distance is0
. - Shortest path to node
1
is directly from0
using red edge. - Node
2
is not reachable from node0
with alternating colors.
- Node
Example 3:
- Input: n = 5, redEdges = [[0, 1], [1, 3]], blueEdges = [[1, 2], [3, 4]]
- Expected Output: [0, 1, 2, -1, -1]
- Justification:
- Node
0
is the start, so distance is0
. - Shortest path to node
1
is directly from0
using red edge. - Shortest path to node
2
is via node1
using red then blue edge. - Shortest path to node
3
is via node1
using red edge, but not with alternative colors. - Shortest path to node
4
is via node3
using red then blue edge, but not with alternative colors.
- Node
Constraints:
- 1 <= n <= 100
- 0 <= redEdges.length, blueEdges.length <= 400
- redEdges[i].length == blueEdges[j].length == 2
- 0 <= ai, bi, uj, vj < n
Solution
To solve this problem, we can use a Breadth-First Search (BFS) approach because it helps find the shortest path in an unweighted graph. BFS explores all possible paths layer by layer, ensuring the shortest path is found. Here, we need to keep track of the colors of the edges to ensure the paths alternate colors. We can use a queue to explore each node, alternating the colors as we go. By maintaining a visited status for each node with both red and blue colors, we ensure we do not revisit nodes in an invalid manner, preventing cycles and redundant paths.
This approach ensures that we check all possible paths from the starting node, considering color alternations. It's efficient since BFS operates in O(V + E) time complexity, where V is the number of vertices and E is the number of edges. Given the graph's constraints, this is an optimal solution.
Step-by-Step Algorithm
-
Initialize Data Structures:
- Create two adjacency lists for the graph: one for red edges and one for blue edges.
- Initialize a 2D result array
res
with size[2][n]
, filled withInteger.MAX_VALUE
, to store the shortest path lengths. Set the starting node0
distance to0
for both colors (i.e.,res[0][0] = 0
andres[1][0] = 0
).
-
Build Graph:
- For each red edge
[ai, bi]
inredEdges
, addbi
to the adjacency list ofai
in the red graph. - For each blue edge
[uj, vj]
inblueEdges
, addvj
to the adjacency list ofuj
in the blue graph.
- For each red edge
-
Initialize BFS Queue:
- Create a queue to store the nodes along with the color of the last edge used to reach them. Initialize the queue with the starting node
0
for both red and blue edges (i.e.,queue.add({0, 0})
andqueue.add({0, 1})
).
- Create a queue to store the nodes along with the color of the last edge used to reach them. Initialize the queue with the starting node
-
Perform BFS:
- While the queue is not empty:
- Dequeue the first element from the queue, which gives the current node and the color of the last edge used to reach it.
- For each neighbor of the current node in the graph of the opposite color:
- If the neighbor has not been visited via the current path (i.e.,
res[1 - color][neighbor] == Integer.MAX_VALUE
), update the shortest path length to this neighbor and add it to the queue.
- If the neighbor has not been visited via the current path (i.e.,
- While the queue is not empty:
-
Generate Answer:
- For each node, the shortest path is the minimum value between the paths found via red and blue edges.
- If no valid path exists, set the distance to
-1
.
Algorithm Walkthrough
Example Input
- n = 4
- redEdges = [[0, 1], [1, 2], [2, 3]]
- blueEdges = [[0, 2], [2, 1], [1, 3]]
-
Initialize Data Structures:
graph[0]
(red edges):[[], [], [], []]
graph[1]
(blue edges):[[], [], [], []]
res
:[[0, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE], [0, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE]]
queue
:[{0, 0}, {0, 1}]
(node, color)
-
Build Graph:
- For red edges:
graph[0][0].add(1)
->graph[0]
:[[1], [], [], []]
graph[0][1].add(2)
->graph[0]
:[[1], [2], [], []]
graph[0][2].add(3)
->graph[0]
:[[1], [2], [3], []]
- For blue edges:
graph[1][0].add(2)
->graph[1]
:[[2], [], [], []]
graph[1][2].add(1)
->graph[1]
:[[2], [], [1], []]
graph[1][1].add(3)
->graph[1]
:[[2], [3], [1], []]
- For red edges:
-
Initialize BFS Queue:
- Queue starts as
[{0, 0}, {0, 1}]
.
- Queue starts as
-
Perform BFS:
- Dequeue
{0, 0}
(node0
with red edge):- Check blue neighbors of
0
:graph[1][0]
:[2]
res[1][2]
isInteger.MAX_VALUE
:- Update
res[1][2] = res[0][0] + 1 = 1
- Enqueue
{2, 1}
- Update
- Check blue neighbors of
- Dequeue
{0, 1}
(node0
with blue edge):- Check red neighbors of
0
:graph[0][0]
:[1]
res[0][1]
isInteger.MAX_VALUE
:- Update
res[0][1] = res[1][0] + 1 = 1
- Enqueue
{1, 0}
- Update
- Check red neighbors of
- Dequeue
{2, 1}
(node2
with blue edge):- Check red neighbors of
2
:graph[0][2]
:[3]
res[0][3]
isInteger.MAX_VALUE
:- Update
res[0][3] = res[1][2] + 1 = 2
- Enqueue
{3, 0}
- Update
- Check red neighbors of
- Dequeue
{1, 0}
(node1
with red edge):- Check blue neighbors of
1
:graph[1][1]
:[3]
res[1][3]
isInteger.MAX_VALUE
:- Update
res[1][3] = res[0][1] + 1 = 2
- Enqueue
{3, 1}
- Update
- Check blue neighbors of
- Dequeue
{3, 0}
(node3
with red edge):- No unvisited blue neighbors.
- Dequeue
{3, 1}
(node3
with blue edge):- No unvisited red neighbors.
- Dequeue
-
Generate Answer:
- For each node
i
, the length of the shortest path is the minimum ofres[0][i]
andres[1][i]
:answer[0] = min(res[0][0], res[1][0]) = 0
answer[1] = min(res[0][1], res[1][1]) = 1
answer[2] = min(res[0][2], res[1][2]) = 1
answer[3] = min(res[0][3], res[1][3]) = 2
- If no valid path exists, set the distance to
-1
.
- For each node
Code
Complexity Analysis
Time complexity
The time complexity of the algorithm is O(V + E), where (V) is the number of vertices (nodes) and (E) is the number of edges. This is because the BFS traversal explores each vertex and edge once.
Space Complexity
The space complexity is also O(V + E), due to the space needed for the graph representation and the BFS queue.
Table of Contents
Problem Statement
Examples
Solution
Step-by-Step Algorithm
Algorithm Walkthrough
Code
Complexity Analysis
Time complexity
Space Complexity