这道题的核心是找到两个节点在完全二叉树中的路径长度,然后计算环的长度。

关键思路:

1. 完全二叉树的节点编号规律:节点 i 的父节点是 i/2
2. 两个节点之间的路径长度 = 深度差 + 2 × LCA深度差
3. 环的长度 = 路径长度 + 1(加回重复的LCA节点)

算法步骤:

1. 对每个查询 (a, b):
   · 记录初始节点 a, b
   · 分别向上追溯,记录路径
   · 找到它们的最近公共祖先(LCA)
   · 计算路径长度:(depth[a]-depth[lca]) + (depth[b]-depth[lca])
   · 环长 = 路径长度 + 1

优化方法:
不需要显式计算深度,可以同时向上移动两个节点直到相遇:

```java
public int[] cycleLengthQueries(int n, int[][] queries) {
    int[] ans = new int[queries.length];
    
    for (int i = 0; i < queries.length; i++) {
        int a = queries[i][0];
        int b = queries[i][1];
        
        int pathLen = 0;
        
        // 同时向上移动,直到相遇
        while (a != b) {
            if (a > b) {
                a /= 2;
            } else {
                b /= 2;
            }
            pathLen++;
        }
        
        // 环的长度 = 路径长度 + 1
        ans[i] = pathLen + 1;
    }
    
    return ans;
}
```

时间复杂度: O(q × log n),其中 q 是查询数量,n 是树的高度
空间复杂度: O(1) 额外空间

原理说明:

· 每次将较大的节点除以2(上移一层)
· 当两个节点相遇时,相遇点就是LCA
· 移动次数就是两个节点到LCA的边数之和
· 加上连接LCA到自身的边,形成环

这样就能高效计算出每个查询对应的环长。

 

更多推荐