3532. Path Existence Queries in a Graph I
MediumView on LeetCode
Problem Overview
Nodes i and j are connected when |nums[i] − nums[j]| ≤ maxDiff.
Intuition
Nodes i and j are connected when |nums[i] − nums[j]| ≤ maxDiff. Because nums is sorted, any path stays inside a contiguous block of indices: if two indices are in the same component, every index between them is too. So only check consecutive pairs — union i with i−1 when their values are close enough, then answer queries by comparing DSU roots.
Algorithm
- 1Initialize Union-Find on n nodes.
- 2For i = 1 … n−1: if nums[i] − nums[i−1] ≤ maxDiff, union(i, i−1).
- 3For each query [u, v]: answer[i] = (Find(u) == Find(v)).
- 4Equivalently, label each contiguous “good-gap” segment with one component id.
Example Walkthrough
Input: n = 4, nums = [2,5,6,8], maxDiff = 2, queries = [[0,1],[0,2],[1,3],[2,3]]
- 1.Adjacent gaps: |5−2|=3 > 2 → break after index 0. |6−5|=1 and |8−6|=2 → indices 1–3 form one component.
- 2.Component ids: [0, 1, 1, 1].
- 3.Query [0,1]: different components → false.
- 4.Query [0,2]: 0 vs component 1 → false.
- 5.Query [1,3]: same component → true (path 1→2→3).
- 6.Query [2,3]: same component → true (direct edge).
Output: [false, false, true, true]
Common Pitfalls
- •Only adjacent unions are enough because nums is sorted — do not union all pairs O(n²).
- •Use nums[i] − nums[i−1] (non-negative) instead of Math.Abs on sorted input.
- •Self-queries [u,u] are always true once a node is in its own set.
3532.cs
C#
// Approach: nums is sorted, so connected components are contiguous index ranges where each
// adjacent gap satisfies |nums[i] - nums[i-1]| <= maxDiff. Union those neighbors in DSU;
// each query is true iff Find(u) == Find(v).
// Time: O(n α(n) + q) Space: O(n)
public class Solution
{
public bool[] PathExistenceQueries(int n, int[] nums, int maxDiff, int[][] queries)
{
bool[] ans = new bool[queries.Length];
UnionFind uf = new UnionFind(n);
for (int i = 1; i < n; ++i)
{
if (Math.Abs(nums[i] - nums[i - 1]) <= maxDiff)
uf.UnionByRank(i, i - 1);
}
for (int i = 0; i < queries.Length; ++i)
{
int u = queries[i][0];
int v = queries[i][1];
ans[i] = uf.Find(u) == uf.Find(v);
}
return ans;
}
}
public class UnionFind
{
private int[] id;
private int[] rank;
public UnionFind(int n)
{
id = new int[n];
rank = new int[n];
for (int i = 0; i < n; ++i)
id[i] = i;
}
public void UnionByRank(int u, int v)
{
int i = Find(u);
int j = Find(v);
if (i == j)
return;
if (rank[i] < rank[j])
id[i] = j;
else if (rank[i] > rank[j])
id[j] = i;
else
{
id[i] = j;
++rank[j];
}
}
public int Find(int u)
{
if (id[u] == u)
return u;
return id[u] = Find(id[u]);
}
}Was this solution helpful?