2509. 查询树中环的长度
前言
「力扣题解」系列致力于分享有价值的题目、探讨更优秀的解法。
这是本系列的第 15 篇题解,更多题解关注 Somnia1337@力扣。
题目描述
难度:🔴困难
标签:#树二叉树
给你一个整数 ,表示一棵含有 个节点的 完全二叉树。根节点的编号为 ,其余每层结点的编号从左至右依次连续填充(见示例图)。
给你一个查询数组,每次查询给出两个结点编号 ,表示在树中新连接一条边 。注意:原本不存在边 ,且各查询相互独立(边的连接是临时的)。返回一个答案数组,对每次查询,回答连接新边后树上环的长度。
输入: n=3, queries=[[5,3],[4,7],[2,3]]
输出: [4,5,3]
解释:
上面 3 幅图展示了每次查询后树的情况
红色边为查询要求添加的边
红色结点为环上结点
对应的环长分别为 [4,5,3]
解题思路
树 有 个结点、 条边,如果再加 1 条边,得到的 点 边图称为 基环树。本题就是求基环树的环长。
记 为 和 的 最近公共祖先(Lowest Common Ancestor),见下图:
环长即为 分别到 、 的距离之和再加上新连接的边 。
根据题设结点编号的特殊性,每个结点 的两个子结点为 、,那么反推得到一个结点 的父结点为 。
找 时,在一个 while
内比较 、 大小(深度,值大者深度大或在同一层),持续将较深者 /2
上移至其父结点,直到 ,此时相遇的结点即为 。
在 while
的同时进行计数,结束后,本次查询的答案即为计数 +1
。
复杂度
- 时间复杂度:, 为
queries
的长度,回答每次查询的复杂度为 - 空间复杂度:
代码
Java
class Solution {
public int[] cycleLengthQueries(int n, int[][] queries) {
int[] ans = new int[queries.length];
for (int i = 0; i < queries.length; i++) {
int cnt = 1, a = queries[i][0], b = queries[i][1];
while (a != b) {
if (a > b) a /= 2; // 上移 a
else b /= 2; // 上移 b
cnt++; // 计数 +1
}
ans[i] = cnt;
}
return ans;
}
}
最后
更多系列「外源推文」&「生活分享」关注公众号: