There are n types of units indexed from 0 to n - 1. You are given a 2D integer array conversions of length n - 1, where conversions[i] = [sourceUnit_i, targetUnit_i, conversionFactor_i]. This indicates that a single unit of type sourceUnit_i is equivalent to conversionFactor_i units of type targetUnit_i.
You are also given a 2D integer array queries of length q, where queries[i] = [unitA_i, unitB_i]. Return an array answer of length q where answer[i] is the number of units of type unitB_i equivalent to 1 unit of type unitA_i, and can be represented as p/q where p and q are coprime.
Return each answer[i] as p * q^(-1) mod (10^9 + 7), where q^(-1) represents the multiplicative inverse of q modulo 10^9 + 7.
💡 Note:For query [0,2]: 0→1 (×3) then 1→2 (×2), so 1 unit of type 0 = 6 units of type 2. For query [1,0]: reverse conversion 1→0 is 1/3, which as modular arithmetic gives 333333336.
The key insight is to model unit conversions as a graph where nodes are unit types and edges are conversion ratios. Build a graph from the conversion array, then use DFS to find paths between query units and calculate the conversion ratio along the path. The result must be expressed as p×q-1 mod (109+7) using modular arithmetic. Best approach uses memoization to cache computed ratios. Time: O(n + q), Space: O(n²)
Common Approaches
✓
Brute Force Path Search
⏱️ Time: O(q × n)
Space: O(n)
Build a graph from conversions and for each query, use DFS to explore all possible paths from source to target unit. Calculate the conversion ratio along each path.
Optimized Graph Traversal with Memoization
⏱️ Time: O(n + q)
Space: O(n²)
Build the graph once and use memoization to store previously calculated conversion ratios. This avoids recalculating the same conversions for multiple queries.
Brute Force Path Search — Algorithm Steps
Build adjacency list from conversions
For each query, use DFS to find path from source to target
Calculate conversion ratio along the path
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Build Graph
Create bidirectional graph from conversions
2
DFS Search
Use DFS to find path from source to target unit
3
Calculate Ratio
Multiply conversion factors along the path
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MOD 1000000007
#define MAX_NODES 100
typedef struct {
long long numerator, denominator;
} Fraction;
typedef struct Edge {
int neighbor;
Fraction ratio;
struct Edge* next;
} Edge;
static Edge* graph[MAX_NODES];
static int visited[MAX_NODES];
long long modPow(long long base, long long exp, long long mod) {
long long result = 1;
base %= mod;
while (exp > 0) {
if (exp % 2 == 1) result = (result * base) % mod;
base = (base * base) % mod;
exp /= 2;
}
return result;
}
long long modInverse(long long a) {
return modPow(a, MOD - 2, MOD);
}
long long gcd(long long a, long long b) {
if (a < 0) a = -a;
if (b < 0) b = -b;
return b == 0 ? a : gcd(b, a % b);
}
Fraction createFraction(long long num, long long den) {
if (den == 0) {
printf("Error: Division by zero\n");
exit(1);
}
long long g = gcd(num, den);
Fraction f;
f.numerator = num / g;
f.denominator = den / g;
if (f.denominator < 0) {
f.numerator = -f.numerator;
f.denominator = -f.denominator;
}
return f;
}
Fraction multiplyFractions(Fraction a, Fraction b) {
return createFraction(a.numerator * b.numerator, a.denominator * b.denominator);
}
void addEdge(int src, int dst, Fraction ratio) {
Edge* edge = malloc(sizeof(Edge));
edge->neighbor = dst;
edge->ratio = ratio;
edge->next = graph[src];
graph[src] = edge;
}
Fraction* dfs(int start, int target) {
if (start == target) {
Fraction* result = malloc(sizeof(Fraction));
*result = createFraction(1, 1);
return result;
}
visited[start] = 1;
Edge* edge = graph[start];
while (edge) {
if (!visited[edge->neighbor]) {
Fraction* result = dfs(edge->neighbor, target);
if (result != NULL) {
Fraction finalResult = multiplyFractions(edge->ratio, *result);
free(result);
result = malloc(sizeof(Fraction));
*result = finalResult;
visited[start] = 0;
return result;
}
}
edge = edge->next;
}
visited[start] = 0;
return NULL;
}
void parse2DArray(const char* str, int arr[][3], int* rows) {
*rows = 0;
const char* p = str;
// Skip initial '['
while (*p && *p != '[') p++;
if (*p == '[') p++;
while (*p) {
// Skip whitespace and commas
while (*p == ' ' || *p == ',') p++;
if (*p == ']') break;
// Expect '[' for new row
if (*p == '[') {
p++;
int col = 0;
while (*p && *p != ']' && col < 3) {
while (*p == ' ' || *p == ',') p++;
if (*p != ']' && *p != '\0') {
arr[*rows][col++] = (int)strtol(p, (char**)&p, 10);
}
}
if (*p == ']') p++;
(*rows)++;
} else {
break;
}
}
}
void parseQueries(const char* str, int arr[][2], int* rows) {
*rows = 0;
const char* p = str;
// Skip initial '['
while (*p && *p != '[') p++;
if (*p == '[') p++;
while (*p) {
// Skip whitespace and commas
while (*p == ' ' || *p == ',') p++;
if (*p == ']') break;
// Expect '[' for new row
if (*p == '[') {
p++;
int col = 0;
while (*p && *p != ']' && col < 2) {
while (*p == ' ' || *p == ',') p++;
if (*p != ']' && *p != '\0') {
arr[*rows][col++] = (int)strtol(p, (char**)&p, 10);
}
}
if (*p == ']') p++;
(*rows)++;
} else {
break;
}
}
}
int* solution(int conversions[][3], int conversionsSize, int queries[][2], int queriesSize, int* returnSize) {
*returnSize = queriesSize;
int* result = malloc(queriesSize * sizeof(int));
// Initialize graph
for (int i = 0; i < MAX_NODES; i++) {
graph[i] = NULL;
visited[i] = 0;
}
// Build graph
for (int i = 0; i < conversionsSize; i++) {
int src = conversions[i][0];
int dst = conversions[i][1];
int factor = conversions[i][2];
addEdge(src, dst, createFraction(factor, 1));
addEdge(dst, src, createFraction(1, factor));
}
// Process queries
for (int i = 0; i < queriesSize; i++) {
memset(visited, 0, sizeof(visited));
Fraction* ratio = dfs(queries[i][0], queries[i][1]);
if (ratio == NULL) {
result[i] = 0;
} else {
long long p = ratio->numerator % MOD;
long long q = ratio->denominator % MOD;
if (p < 0) p += MOD;
if (q < 0) q += MOD;
result[i] = (p * modInverse(q)) % MOD;
free(ratio);
}
}
return result;
}
int main() {
char line1[10000], line2[10000];
fgets(line1, sizeof(line1), stdin);
fgets(line2, sizeof(line2), stdin);
int conversions[1000][3], queries[1000][2];
int conversionsSize, queriesSize;
parse2DArray(line1, conversions, &conversionsSize);
parseQueries(line2, queries, &queriesSize);
int returnSize;
int* result = solution(conversions, conversionsSize, queries, queriesSize, &returnSize);
printf("[");
for (int i = 0; i < returnSize; i++) {
if (i > 0) printf(",");
printf("%d", result[i]);
}
printf("]\n");
free(result);
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(q × n)
For each query, DFS traverses up to n nodes in the graph
n
2n
✓ Linear Growth
Space Complexity
O(n)
Adjacency list stores n-1 edges plus recursion stack
n
2n
⚡ Linearithmic Space
25.0K Views
MediumFrequency
~35 minAvg. Time
890 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.