Welcome to Subscribe On Youtube
3534. Path Existence Queries in a Graph II
Description
You are given an integer n representing the number of nodes in a graph, labeled from 0 to n - 1.
You are also given an integer array nums of length n and an integer maxDiff.
An undirected edge exists between nodes i and j if the absolute difference between nums[i] and nums[j] is at most maxDiff (i.e., \|nums[i] - nums[j]\| <= maxDiff).
You are also given a 2D integer array queries. For each queries[i] = [ui, vi], find the minimum distance between nodes ui and vi. If no path exists between the two nodes, return -1 for that query.
Return an array answer, where answer[i] is the result of the ith query.
Note: The edges between the nodes are unweighted.
Example 1:
Input: n = 5, nums = [1,8,3,4,2], maxDiff = 3, queries = [[0,3],[2,4]]
Output: [1,1]
Explanation:
The resulting graph is:

| Query | Shortest Path | Minimum Distance |
|---|---|---|
| [0, 3] | 0 → 3 | 1 |
| [2, 4] | 2 → 4 | 1 |
Thus, the output is [1, 1].
Example 2:
Input: n = 5, nums = [5,3,1,9,10], maxDiff = 2, queries = [[0,1],[0,2],[2,3],[4,3]]
Output: [1,2,-1,1]
Explanation:
The resulting graph is:

| Query | Shortest Path | Minimum Distance |
|---|---|---|
| [0, 1] | 0 → 1 | 1 |
| [0, 2] | 0 → 1 → 2 | 2 |
| [2, 3] | None | -1 |
| [4, 3] | 3 → 4 | 1 |
Thus, the output is [1, 2, -1, 1].
Example 3:
Input: n = 3, nums = [3,6,1], maxDiff = 1, queries = [[0,0],[0,1],[1,2]]
Output: [0,-1,-1]
Explanation:
There are no edges between any two nodes because:
- Nodes 0 and 1:
\|nums[0] - nums[1]\| = \|3 - 6\| = 3 > 1 - Nodes 0 and 2:
\|nums[0] - nums[2]\| = \|3 - 1\| = 2 > 1 - Nodes 1 and 2:
\|nums[1] - nums[2]\| = \|6 - 1\| = 5 > 1
Thus, no node can reach any other node, and the output is [0, -1, -1].
Constraints:
1 <= n == nums.length <= 1050 <= nums[i] <= 1050 <= maxDiff <= 1051 <= queries.length <= 105queries[i] == [ui, vi]0 <= ui, vi < n
Solutions
Solution 1
-
class Solution { public int[] pathExistenceQueries(int n, int[] nums, int maxDiff, int[][] queries) { int[][] pairs = new int[n][2]; for (int i = 0; i < n; i++) { pairs[i][0] = nums[i]; pairs[i][1] = i; } Arrays.sort(pairs, (a, b) -> a[0] - b[0]); int m = 20; int[][] f = new int[n][m]; int r = n - 1; for (int l = n - 1; l >= 0; l--) { while (pairs[r][0] - pairs[l][0] > maxDiff) { r--; } int i = pairs[l][1], j = pairs[r][1]; f[i][0] = j; for (int k = 1; k < m; k++) { f[i][k] = f[f[i][k - 1]][k - 1]; } } int[] ans = new int[queries.length]; for (int t = 0; t < queries.length; t++) { int i = queries[t][0], j = queries[t][1]; if (nums[i] > nums[j]) { int tmp = i; i = j; j = tmp; } if (i == j) { ans[t] = 0; continue; } if (nums[i] == nums[j]) { ans[t] = 1; continue; } int d = 0; for (int k = m - 1; k >= 0; k--) { if (nums[f[i][k]] < nums[j]) { d |= 1 << k; i = f[i][k]; } } if (nums[f[i][0]] < nums[j]) { ans[t] = -1; } else { ans[t] = d + 1; } } return ans; } } -
class Solution { public: vector<int> pathExistenceQueries(int n, vector<int>& nums, int maxDiff, vector<vector<int>>& queries) { vector<pair<int, int>> pairs; for (int i = 0; i < n; i++) { pairs.emplace_back(nums[i], i); } sort(pairs.begin(), pairs.end()); int m = 20; vector<vector<int>> f(n, vector<int>(m)); int r = n - 1; for (int l = n - 1; l >= 0; l--) { while (pairs[r].first - pairs[l].first > maxDiff) { r--; } int i = pairs[l].second, j = pairs[r].second; f[i][0] = j; for (int k = 1; k < m; k++) { f[i][k] = f[f[i][k - 1]][k - 1]; } } vector<int> ans; for (auto& q : queries) { int i = q[0], j = q[1]; if (nums[i] > nums[j]) { swap(i, j); } if (i == j) { ans.push_back(0); continue; } if (nums[i] == nums[j]) { ans.push_back(1); continue; } int d = 0; for (int k = m - 1; k >= 0; k--) { if (nums[f[i][k]] < nums[j]) { d |= 1 << k; i = f[i][k]; } } if (nums[f[i][0]] < nums[j]) { ans.push_back(-1); } else { ans.push_back(d + 1); } } return ans; } }; -
class Solution: def pathExistenceQueries( self, n: int, nums: List[int], maxDiff: int, queries: List[List[int]] ) -> List[int]: pairs = sorted((x, i) for i, x in enumerate(nums)) m = 20 f = [[0] * m for _ in range(n)] r = n - 1 for l in range(n - 1, -1, -1): while pairs[r][0] - pairs[l][0] > maxDiff: r -= 1 i, j = pairs[l][1], pairs[r][1] f[i][0] = j for k in range(1, m): f[i][k] = f[f[i][k - 1]][k - 1] ans = [] for i, j in queries: if nums[i] > nums[j]: i, j = j, i if i == j: ans.append(0) continue if nums[i] == nums[j]: ans.append(1) continue d = 0 for k in range(m - 1, -1, -1): if nums[f[i][k]] < nums[j]: d |= 1 << k i = f[i][k] if nums[f[i][0]] < nums[j]: ans.append(-1) else: ans.append(d + 1) return ans -
func pathExistenceQueries(n int, nums []int, maxDiff int, queries [][]int) []int { pairs := make([][2]int, n) for i, x := range nums { pairs[i] = [2]int{x, i} } sort.Slice(pairs, func(i, j int) bool { return pairs[i][0] < pairs[j][0] }) m := 20 f := make([][]int, n) for i := range f { f[i] = make([]int, m) } r := n - 1 for l := n - 1; l >= 0; l-- { for pairs[r][0]-pairs[l][0] > maxDiff { r-- } i, j := pairs[l][1], pairs[r][1] f[i][0] = j for k := 1; k < m; k++ { f[i][k] = f[f[i][k-1]][k-1] } } ans := make([]int, 0, len(queries)) for _, q := range queries { i, j := q[0], q[1] if nums[i] > nums[j] { i, j = j, i } if i == j { ans = append(ans, 0) continue } if nums[i] == nums[j] { ans = append(ans, 1) continue } d := 0 for k := m - 1; k >= 0; k-- { if nums[f[i][k]] < nums[j] { d |= 1 << k i = f[i][k] } } if nums[f[i][0]] < nums[j] { ans = append(ans, -1) } else { ans = append(ans, d+1) } } return ans } -
function pathExistenceQueries( n: number, nums: number[], maxDiff: number, queries: number[][], ): number[] { const pairs: number[][] = []; for (let i = 0; i < n; i++) { pairs.push([nums[i], i]); } pairs.sort((a, b) => a[0] - b[0]); const m = 20; const f = Array.from({ length: n }, () => Array(m).fill(0)); let r = n - 1; for (let l = n - 1; l >= 0; l--) { while (pairs[r][0] - pairs[l][0] > maxDiff) { r--; } let i = pairs[l][1], j = pairs[r][1]; f[i][0] = j; for (let k = 1; k < m; k++) { f[i][k] = f[f[i][k - 1]][k - 1]; } } const ans: number[] = []; for (const q of queries) { let i = q[0], j = q[1]; if (nums[i] > nums[j]) { [i, j] = [j, i]; } if (i === j) { ans.push(0); continue; } if (nums[i] === nums[j]) { ans.push(1); continue; } let d = 0; for (let k = m - 1; k >= 0; k--) { if (nums[f[i][k]] < nums[j]) { d |= 1 << k; i = f[i][k]; } } if (nums[f[i][0]] < nums[j]) { ans.push(-1); } else { ans.push(d + 1); } } return ans; } -
impl Solution { pub fn path_existence_queries( n: i32, nums: Vec<i32>, max_diff: i32, queries: Vec<Vec<i32>>, ) -> Vec<i32> { let n = n as usize; let mut pairs = Vec::with_capacity(n); for (i, &x) in nums.iter().enumerate() { pairs.push((x, i)); } pairs.sort_unstable(); let m = 20; let mut f = vec![vec![0; m]; n]; let mut r = n - 1; for l in (0..n).rev() { while pairs[r].0 - pairs[l].0 > max_diff { r -= 1; } let (i, j) = (pairs[l].1, pairs[r].1); f[i][0] = j; for k in 1..m { f[i][k] = f[f[i][k - 1]][k - 1]; } } let mut ans = Vec::with_capacity(queries.len()); for q in queries { let (mut i, mut j) = (q[0] as usize, q[1] as usize); if nums[i] > nums[j] { std::mem::swap(&mut i, &mut j); } if i == j { ans.push(0); continue; } if nums[i] == nums[j] { ans.push(1); continue; } let mut d = 0; for k in (0..m).rev() { if nums[f[i][k]] < nums[j] { d |= 1 << k; i = f[i][k]; } } if nums[f[i][0]] < nums[j] { ans.push(-1); } else { ans.push(d + 1); } } ans } }