You are given an undirected tree rooted at node 0 with n nodes numbered from 0 to n - 1, represented by a 2D array edges of length n - 1, where edges[i] = [u_i, v_i, length_i] indicates an edge between nodes u_i and v_i with length length_i.
You are also given an integer array nums, where nums[i] represents the value at node i.
A special path is defined as a downward path from an ancestor node to a descendant node such that all the values of the nodes in that path are unique.
Note that a path may start and end at the same node.
Return an array result of size 2, where result[0] is the length of the longest special path, and result[1] is the minimum number of nodes in all possible longest special paths.
The key insight is to use DFS with backtracking to explore all downward paths while maintaining a set of visited values to ensure uniqueness. Best approach uses DFS with visited set tracking for efficient path exploration. Time: O(n²), Space: O(n)
Common Approaches
✓
Frequency Count
⏱️ Time: N/A
Space: N/A
Sort First
⏱️ Time: N/A
Space: N/A
Brute Force DFS
⏱️ Time: O(n²)
Space: O(n)
For each node, explore all possible downward paths and check if values are unique. Track the maximum path length and count paths with that length.
Optimized DFS with Backtracking
⏱️ Time: O(n²)
Space: O(n)
Build the tree structure and perform DFS from root, using backtracking to efficiently explore all unique paths without redundant work.
Algorithm Steps — Algorithm Steps
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct Edge {
int to;
int length;
struct Edge* next;
} Edge;
Edge* adj[100005];
int nums[100005];
int maxLength = 0;
int minNodes = 1000000;
void addEdge(int from, int to, int length) {
Edge* edge = (Edge*)malloc(sizeof(Edge));
edge->to = to;
edge->length = length;
edge->next = adj[from];
adj[from] = edge;
}
void dfs(int node, int parent, bool used[], int currentLength, int nodeCount) {
if (used[nums[node]]) {
return;
}
// Include current node
used[nums[node]] = true;
nodeCount++;
// Update result
if (currentLength > maxLength || (currentLength == maxLength && nodeCount < minNodes)) {
maxLength = currentLength;
minNodes = nodeCount;
}
// Try extending to children
for (Edge* edge = adj[node]; edge != NULL; edge = edge->next) {
if (edge->to != parent) {
dfs(edge->to, node, used, currentLength + edge->length, nodeCount);
}
}
// Backtrack
used[nums[node]] = false;
}
void solve(int n) {
bool used[100001] = {false};
// Try starting from each node
for (int i = 0; i < n; i++) {
dfs(i, -1, used, 0, 0);
}
}
int main() {
char line[10000];
// Initialize
for (int i = 0; i < 100005; i++) {
adj[i] = NULL;
}
maxLength = 0;
minNodes = 1000000;
// Read edges
fgets(line, sizeof(line), stdin);
// Parse edges
int edgeCount = 0;
char* p = line;
while (*p && *p != '[') p++;
if (*p == '[') p++;
while (*p && *p != ']') {
while (*p == ' ' || *p == ',') p++;
if (*p == '[') {
p++;
int u = (int)strtol(p, &p, 10);
while (*p == ',' || *p == ' ') p++;
int v = (int)strtol(p, &p, 10);
while (*p == ',' || *p == ' ') p++;
int len = (int)strtol(p, &p, 10);
while (*p == ']') p++;
addEdge(u, v, len);
addEdge(v, u, len);
edgeCount++;
} else {
break;
}
}
// Read nums
fgets(line, sizeof(line), stdin);
int n = 0;
p = line;
while (*p && *p != '[') p++;
if (*p == '[') p++;
while (*p && *p != ']') {
while (*p == ' ' || *p == ',') p++;
if (*p == ']' || *p == '\0') break;
nums[n++] = (int)strtol(p, &p, 10);
}
solve(n);
// If no path found or only single nodes, return [0,1]
if (minNodes == 1000000) {
minNodes = 1;
}
printf("[%d,%d]\n", maxLength, minNodes);
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
n
2n
✓ Linear Growth
Space Complexity
n
2n
✓ Linear Space
2.2K Views
MediumFrequency
~35 minAvg. Time
89 Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.