Largest Color Value in a Directed Graph
Leetcode Daily Challenge (9th April, 2023)
Problem Statement:-
There is a directed graph of n
colored nodes and m
edges. The nodes are numbered from 0
to n - 1
.
You are given a string colors
where colors[i]
is a lowercase English letter representing the color of the i<sup>th</sup>
node in this graph (0-indexed). You are also given a 2D array edges
where edges[j] = [a<sub>j</sub>, b<sub>j</sub>]
indicates that there is a directed edge from node a<sub>j</sub>
to node b<sub>j</sub>
.
A valid path in the graph is a sequence of nodes x<sub>1</sub> -> x<sub>2</sub> -> x<sub>3</sub> -> ... -> x<sub>k</sub>
such that there is a directed edge from x<sub>i</sub>
to x<sub>i+1</sub>
for every 1 <= i < k
. The color value of the path is the number of nodes that are colored the most frequently occurring color along that path.
Return the largest color value of any valid path in the given graph, or -1
if the graph contains a cycle.
Link: https://leetcode.com/problems/largest-color-value-in-a-directed-graph/description/
Problem Explanation with examples:-
Example 1
Input: colors = "abaca", edges = [[0,1],[0,2],[2,3],[3,4]]
Output: 3
Explanation: The path 0 -> 2 -> 3 -> 4 contains 3 nodes that are colored "a" (red in the above image).
Example 2
Input: colors = "a", edges = [[0,0]]
Output: -1
Explanation: There is a cycle from 0 to 0.
Constraints
n == colors.length
m == edges.length
1 <= n <= 10<sup>5</sup>
0 <= m <= 10<sup>5</sup>
colors
consists of lowercase English letters.0 <= a<sub>j</sub>, b<sub>j</sub> < n
Intuition:-
For each node, we need to find the max number of nodes that can be reached from it and have the same color as the node.
DFS is a good choice for this problem. We can use a colormap to store the max number of nodes that can be reached from a node and have the same color as the node.
We can use a path set to detect if there is a cycle in the graph and a visit set to detect if a node has been visited.
Using the adj list, we can traverse the graph and update the colormap for each node using the colormap of its neighbors.
Solution:-
Create an adj list. Iterate through the edges and add the edges to the adj list.
Create a dfs function that takes a node as input. If the node is in the path set, return infinity. If the node is in the visit set, return 0.
Add the node to the visit set and the path set.
Get the color index of the node. Update the colormap of the node at the color index to 1.
Iterate through the neighbors of the node. If the dfs function returns infinity, return infinity.
Iterate through the colormap of the neighbor. Update the colormap of the node at the color index to the max of the current value and the value of the neighbor at the color index plus 1 if the color index is the same as the color index of the node and 0 otherwise.
Remove the node from the path set.
Return the max of the colormap of the node.
Create a visit set and a path set.
Create a colormap of size n*26 and initialize it to 0.
Iterate through the nodes. Update the ans to the max of the ans and the dfs function of the node.
Return -1 if the ans is infinity and the ans otherwise.
Code:-
JAVA Solution
class Solution {
public int largestPathValue(String colors, int[][] edges) {
int n = colors.length();
int[][] colormap = new int[n][26];
Map<Integer, List<Integer>> adj = new HashMap<>();
int ans = 0;
for (int i = 0; i < n; i++) {
Arrays.fill(colormap[i], 0);
}Add the node to the visit set and the path set.
for (int[] edge : edges) {
int src = edge[0];
int dst = edge[1];
if (!adj.containsKey(src)) {
adj.put(src, new ArrayList<Integer>());
}
adj.get(src).add(dst);
}
Set<Integer> visit = new HashSet<>();
Set<Integer> path = new HashSet<>();
for (int i = 0; i < n; i++) {
if (!visit.contains(i)) {
int val = dfs(i, visit, path, colormap, adj, colors);
if (val == Integer.MAX_VALUE) return -1;
ans = Math.max(ans, val);
}
}
return ans;
}
private int dfs(int node, Set<Integer> visit, Set<Integer> path, int[][] colormap, Map<Integer, List<Integer>> adj, String colors) {
if (path.contains(node)) {
return Integer.MAX_VALUE;
}
if (visit.contains(node)) {
return 0;
}
visit.add(node);
path.add(node);
int colorIdx = colors.charAt(node) - 'a';
colormap[node][colorIdx] = 1;
if (adj.containsKey(node)) {
for (int nei : adj.get(node)) {
int val = dfs(nei, visit, path, colormap, adj, colors);
if (val == Integer.MAX_VALUE) return Integer.MAX_VALUE;
for (int col = 0; col < 26; col++) {
colormap[node][col] = Math.max(colormap[node][col], ((col == colorIdx) ? 1 : 0) + colormap[nei][col]);
}
}
}
path.remove(node);
int res = 0;
for (int i = 0; i < 26; i++) {
res = Math.max(res, colormap[node][i]);
}
return res;
}
}
Python Solution
class Solution:
def largestPathValue(self, colors: str, edges: List[List[int]]) -> int:
adj = defaultdict(list)
for src,dst in edges:
adj[src].append(dst)
def dfs(node):
if node in path:
return float('inf')
if node in visit:
return 0
visit.add(node)
path.add(node)
colorIdx = ord(colors[node]) - 97
colormap[node][colorIdx] = 1
for nei in adj[node]:
if dfs(nei) == float('inf'): return float('inf')
for col in range(26):
colormap[node][col] = max(colormap[node][col], (1 if col==colorIdx else 0)+colormap[nei][col])
path.remove(node)
return max(colormap[node])
n = len(colors)
ans = 0
visit = set()
path = set()
colormap = [[0]*26 for i in range(n)]
for i in range(n):
ans = max(ans,dfs(i))
return -1 if ans==float('inf') else ans
Complexity Analysis:-
TIME:-
The time complexity is O(n * (m + e)), where n is the number of nodes, m is the length of the alphabet (26 in this case), and e is the number of edges in the graph. This is because we perform a DFS traversal for each node, and for each DFS, we iterate through the edges and perform a maximum of 26 operations for each edge.
SPACE:-
The space complexity is O(n * m), where n is the number of nodes and m is the length of the alphabet. This is because we create a 2D array of size n x m to keep track of the count of each color at each node. We also use sets to keep track of visited and current path nodes, which can take up to O(n) space in the worst case. Therefore, the overall space complexity is O(n m).