🧠
Brute Force (DFS with Path Tracking)
💡 Starting with brute force helps understand the problem's complexity by trying all paths explicitly, which is intuitive but inefficient for large graphs.
Intuition
Try all possible paths from every node, track colors along the path, and record the maximum frequency of any color. If a cycle is detected during traversal, return -1.
Algorithm
- For each node, perform a DFS to explore all paths starting from it.
- Track the frequency of colors along the current path.
- If a cycle is detected (node revisited in current path), return -1.
- Update the global maximum color frequency found on any path.
💡 This approach is straightforward but the exponential number of paths makes it impractical for large inputs.
from collections import defaultdict
import sys
sys.setrecursionlimit(10**7)
def largestPathValue(colors, edges):
n = len(colors)
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
max_color_value = [0] # Use list to allow updates inside dfs
visited = [0] * n # 0=unvisited,1=visiting,2=visited
def dfs(node, path_colors):
if visited[node] == 1:
return -1 # cycle detected
if visited[node] == 2:
return 0 # already processed
visited[node] = 1
path_colors[colors[node]] += 1
current_max = path_colors[colors[node]]
for nei in graph[node]:
res = dfs(nei, path_colors)
if res == -1:
return -1
current_max = max(current_max, res)
max_color_value[0] = max(max_color_value[0], current_max)
path_colors[colors[node]] -= 1
visited[node] = 2
return current_max
for i in range(n):
res = dfs(i, defaultdict(int))
if res == -1:
return -1
return max_color_value[0]
# Example usage
if __name__ == '__main__':
print(largestPathValue("abaca", [[0,1],[0,2],[2,3],[3,4]])) # Output: 3
print(largestPathValue("a", [[0,0]])) # Output: -1
Line Notes
sys.setrecursionlimit(10**7)Increase recursion limit to avoid stack overflow on deep recursion
visited = [0] * nTrack node states to detect cycles and avoid reprocessing
if visited[node] == 1:Detect cycle if node is currently in recursion stack
path_colors[colors[node]] += 1Increment count of current node's color along the path
max_color_value[0] = max(max_color_value[0], current_max)Update global max color value during DFS
import java.util.*;
public class LargestColorValue {
public static int largestPathValue(String colors, int[][] edges) {
int n = colors.length();
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < n; i++) graph.add(new ArrayList<>());
for (int[] e : edges) graph.get(e[0]).add(e[1]);
int[] visited = new int[n]; // 0=unvisited,1=visiting,2=visited
int[] maxColorValue = new int[1];
for (int i = 0; i < n; i++) {
if (dfs(i, graph, colors, visited, new HashMap<>(), maxColorValue) == -1) return -1;
}
return maxColorValue[0];
}
private static int dfs(int node, List<List<Integer>> graph, String colors, int[] visited, Map<Character, Integer> pathColors, int[] maxColorValue) {
if (visited[node] == 1) return -1; // cycle
if (visited[node] == 2) return 0;
visited[node] = 1;
char c = colors.charAt(node);
pathColors.put(c, pathColors.getOrDefault(c, 0) + 1);
int currentMax = pathColors.get(c);
for (int nei : graph.get(node)) {
int res = dfs(nei, graph, colors, visited, pathColors, maxColorValue);
if (res == -1) return -1;
currentMax = Math.max(currentMax, res);
}
maxColorValue[0] = Math.max(maxColorValue[0], currentMax);
pathColors.put(c, pathColors.get(c) - 1);
if (pathColors.get(c) == 0) pathColors.remove(c);
visited[node] = 2;
return currentMax;
}
public static void main(String[] args) {
System.out.println(largestPathValue("abaca", new int[][]{{0,1},{0,2},{2,3},{3,4}})); // 3
System.out.println(largestPathValue("a", new int[][]{{0,0}})); // -1
}
}
Line Notes
int[] visited = new int[n];Track node visitation state for cycle detection
if (visited[node] == 1) return -1;Detect cycle by revisiting node in current path
pathColors.put(c, pathColors.getOrDefault(c, 0) + 1);Increment color count for current path
maxColorValue[0] = Math.max(maxColorValue[0], currentMax);Update global max color value
pathColors.put(c, pathColors.get(c) - 1);Backtrack color count after DFS call
if (pathColors.get(c) == 0) pathColors.remove(c);Clean up map to avoid stale entries
#include <bits/stdc++.h>
using namespace std;
int n;
vector<vector<int>> graph;
string colors;
vector<int> visited; // 0=unvisited,1=visiting,2=visited
int maxColorValue = 0;
int dfs(int node, unordered_map<char,int>& pathColors) {
if (visited[node] == 1) return -1; // cycle
if (visited[node] == 2) return 0;
visited[node] = 1;
pathColors[colors[node]]++;
int currentMax = pathColors[colors[node]];
for (int nei : graph[node]) {
int res = dfs(nei, pathColors);
if (res == -1) return -1;
currentMax = max(currentMax, res);
}
maxColorValue = max(maxColorValue, currentMax);
pathColors[colors[node]]--;
if (pathColors[colors[node]] == 0) pathColors.erase(colors[node]);
visited[node] = 2;
return currentMax;
}
int largestPathValue(string _colors, vector<vector<int>>& edges) {
colors = _colors;
n = colors.size();
graph.assign(n, vector<int>());
for (auto& e : edges) graph[e[0]].push_back(e[1]);
visited.assign(n, 0);
maxColorValue = 0;
for (int i = 0; i < n; i++) {
unordered_map<char,int> pathColors;
int res = dfs(i, pathColors);
if (res == -1) return -1;
}
return maxColorValue;
}
int main() {
cout << largestPathValue("abaca", vector<vector<int>>{{0,1},{0,2},{2,3},{3,4}}) << "\n"; // 3
cout << largestPathValue("a", vector<vector<int>>{{0,0}}) << "\n"; // -1
return 0;
}
Line Notes
visited.assign(n, 0);Initialize visitation states for all nodes
if (visited[node] == 1) return -1;Cycle detection by checking recursion stack
pathColors[colors[node]]++;Count current node's color in path
maxColorValue = max(maxColorValue, currentMax);Update global maximum color count
pathColors[colors[node]]--;Backtrack color count after DFS call
if (pathColors[colors[node]] == 0) pathColors.erase(colors[node]);Remove color entry if count is zero
function largestPathValue(colors, edges) {
const n = colors.length;
const graph = Array.from({length: n}, () => []);
for (const [u, v] of edges) graph[u].push(v);
const visited = new Array(n).fill(0); // 0=unvisited,1=visiting,2=visited
let maxColorValue = 0;
function dfs(node, pathColors) {
if (visited[node] === 1) return -1; // cycle
if (visited[node] === 2) return 0;
visited[node] = 1;
pathColors.set(colors[node], (pathColors.get(colors[node]) || 0) + 1);
let currentMax = pathColors.get(colors[node]);
for (const nei of graph[node]) {
const res = dfs(nei, pathColors);
if (res === -1) return -1;
currentMax = Math.max(currentMax, res);
}
maxColorValue = Math.max(maxColorValue, currentMax);
pathColors.set(colors[node], pathColors.get(colors[node]) - 1);
if (pathColors.get(colors[node]) === 0) pathColors.delete(colors[node]);
visited[node] = 2;
return currentMax;
}
for (let i = 0; i < n; i++) {
const pathColors = new Map();
const res = dfs(i, pathColors);
if (res === -1) return -1;
}
return maxColorValue;
}
// Example usage
console.log(largestPathValue("abaca", [[0,1],[0,2],[2,3],[3,4]])); // 3
console.log(largestPathValue("a", [[0,0]])); // -1
Line Notes
const visited = new Array(n).fill(0);Track node states to detect cycles and avoid reprocessing
if (visited[node] === 1) return -1;Detect cycle if node is currently in recursion stack
pathColors.set(colors[node], (pathColors.get(colors[node]) || 0) + 1);Increment count of current node's color along the path
maxColorValue = Math.max(maxColorValue, currentMax);Update global maximum color count
pathColors.set(colors[node], pathColors.get(colors[node]) - 1);Backtrack color count after DFS call
if (pathColors.get(colors[node]) === 0) pathColors.delete(colors[node]);Remove color entry if count is zero
TimeO(n * (n + e)) in worst case due to exploring all paths
SpaceO(n) recursion stack + O(n) for path color counts
DFS explores all paths from each node, which can be exponential in worst case due to repeated paths and no memoization.
💡 For n=20, this could mean billions of operations, making it impractical for large inputs.
Interview Verdict: TLE
This approach is too slow for large graphs but is useful to understand the problem and why optimization is needed.