Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
You are given an integer n. There is a complete binary tree with 2n - 1 nodes. The root of that tree is the node with the value 1, and every node with a value val in the range [1, 2n - 1 - 1] has two children where:
2 * val, and2 * val + 1.You are also given a 2D integer array queries of length m, where queries[i] = [ai, bi]. For each query, solve the following problem:
ai and bi.ai and bi.Note that:
Return an array answer of length m where answer[i] is the answer to the ith query.
Example 1:
Input: n = 3, queries = [[5,3],[4,7],[2,3]] Output: [4,5,3] Explanation: The diagrams above show the tree of 23 - 1 nodes. Nodes colored in red describe the nodes in the cycle after adding the edge. - After adding the edge between nodes 3 and 5, the graph contains a cycle of nodes [5,2,1,3]. Thus answer to the first query is 4. We delete the added edge and process the next query. - After adding the edge between nodes 4 and 7, the graph contains a cycle of nodes [4,2,1,3,7]. Thus answer to the second query is 5. We delete the added edge and process the next query. - After adding the edge between nodes 2 and 3, the graph contains a cycle of nodes [2,1,3]. Thus answer to the third query is 3. We delete the added edge.
Example 2:
Input: n = 2, queries = [[1,2]] Output: [2] Explanation: The diagram above shows the tree of 22 - 1 nodes. Nodes colored in red describe the nodes in the cycle after adding the edge. - After adding the edge between nodes 1 and 2, the graph contains a cycle of nodes [2,1]. Thus answer for the first query is 2. We delete the added edge.
Constraints:
2 <= n <= 30m == queries.length1 <= m <= 105queries[i].length == 21 <= ai, bi <= 2n - 1ai != biProblem summary: You are given an integer n. There is a complete binary tree with 2n - 1 nodes. The root of that tree is the node with the value 1, and every node with a value val in the range [1, 2n - 1 - 1] has two children where: The left node has the value 2 * val, and The right node has the value 2 * val + 1. You are also given a 2D integer array queries of length m, where queries[i] = [ai, bi]. For each query, solve the following problem: Add an edge between the nodes with values ai and bi. Find the length of the cycle in the graph. Remove the added edge between nodes with values ai and bi. Note that: A cycle is a path that starts and ends at the same node, and each edge in the path is visited only once. The length of a cycle is the number of edges visited in the cycle. There could be multiple edges between two nodes in the tree after adding the edge of the query. Return an array answer of length
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Tree
3 [[5,3],[4,7],[2,3]]
2 [[1,2]]
populating-next-right-pointers-in-each-node)lowest-common-ancestor-of-a-binary-tree)path-in-zigzag-labelled-binary-tree)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #2509: Cycle Length Queries in a Tree
class Solution {
public int[] cycleLengthQueries(int n, int[][] queries) {
int m = queries.length;
int[] ans = new int[m];
for (int i = 0; i < m; ++i) {
int a = queries[i][0], b = queries[i][1];
int t = 1;
while (a != b) {
if (a > b) {
a >>= 1;
} else {
b >>= 1;
}
++t;
}
ans[i] = t;
}
return ans;
}
}
// Accepted solution for LeetCode #2509: Cycle Length Queries in a Tree
func cycleLengthQueries(n int, queries [][]int) []int {
ans := []int{}
for _, q := range queries {
a, b := q[0], q[1]
t := 1
for a != b {
if a > b {
a >>= 1
} else {
b >>= 1
}
t++
}
ans = append(ans, t)
}
return ans
}
# Accepted solution for LeetCode #2509: Cycle Length Queries in a Tree
class Solution:
def cycleLengthQueries(self, n: int, queries: List[List[int]]) -> List[int]:
ans = []
for a, b in queries:
t = 1
while a != b:
if a > b:
a >>= 1
else:
b >>= 1
t += 1
ans.append(t)
return ans
// Accepted solution for LeetCode #2509: Cycle Length Queries in a Tree
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #2509: Cycle Length Queries in a Tree
// class Solution {
// public int[] cycleLengthQueries(int n, int[][] queries) {
// int m = queries.length;
// int[] ans = new int[m];
// for (int i = 0; i < m; ++i) {
// int a = queries[i][0], b = queries[i][1];
// int t = 1;
// while (a != b) {
// if (a > b) {
// a >>= 1;
// } else {
// b >>= 1;
// }
// ++t;
// }
// ans[i] = t;
// }
// return ans;
// }
// }
// Accepted solution for LeetCode #2509: Cycle Length Queries in a Tree
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #2509: Cycle Length Queries in a Tree
// class Solution {
// public int[] cycleLengthQueries(int n, int[][] queries) {
// int m = queries.length;
// int[] ans = new int[m];
// for (int i = 0; i < m; ++i) {
// int a = queries[i][0], b = queries[i][1];
// int t = 1;
// while (a != b) {
// if (a > b) {
// a >>= 1;
// } else {
// b >>= 1;
// }
// ++t;
// }
// ans[i] = t;
// }
// return ans;
// }
// }
Use this to step through a reusable interview workflow for this problem.
BFS with a queue visits every node exactly once — O(n) time. The queue may hold an entire level of the tree, which for a complete binary tree is up to n/2 nodes = O(n) space. This is optimal in time but costly in space for wide trees.
Every node is visited exactly once, giving O(n) time. Space depends on tree shape: O(h) for recursive DFS (stack depth = height h), or O(w) for BFS (queue width = widest level). For balanced trees h = log n; for skewed trees h = n.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Recursive traversal assumes children always exist.
Usually fails on: Leaf nodes throw errors or create wrong depth/path values.
Fix: Handle null/base cases before recursive transitions.