2024.4.6
题目来源
我的题解
方法一 哈希表 超内存
使用一个哈希表存储每个节点的祖先节点。
时间复杂度:O(n)
空间复杂度:O( n 2 n^2 n2)
class TreeAncestor {
Map<Integer,List<Integer>> res;
int[] parent;
int n;
public TreeAncestor(int n, int[] parent) {
this.n=n;
this.parent=parent;
res=new HashMap<>();
computedAncestor(n,parent);
}
private void computedAncestor(int n,int[] parent){
for(int i=1;i<n;i++){
List<Integer> l=res.getOrDefault(i,new ArrayList<>());
l.add(parent[i]);
l.addAll(res.getOrDefault(parent[i],new ArrayList<>()));
res.put(i,l);
}
}
public int getKthAncestor(int node, int k) {
List<Integer> t=res.getOrDefault(node,new ArrayList<>());
return k<=t.size()?t.get(k-1):-1;
// while(parent[node]!=-1){
// k--;
// node=parent[node];
// }
// return k!=-1?node:-1;
}
}
方法二 树上倍增
倍增的思路类似于动态规划,定义 ancestors[i][j] 表示节点 i 的第 2 j 2^j 2j个祖先。此题中,树最多有 50000 个节点,因此 ancestors 的第二维度的最大值可以设为 16。根据定义,ancestors[i][0]=parent[i]。状态转移方程是 ancestors[i][j]=ancestors[ancestors[i][j−1]][j−1],即当前节点的第 2 j 2^j 2j个祖先,是他的第 2 j − 1 2^{j-1} 2j−1 个祖先的第 2 j − 1 2^{j-1} 2j−1 个祖先。当第 2 j 2^{j} 2j 个祖先不存在时,记为 −1。
查询时,需要将 k 的二进制表示从最低位到最高位依次进行判断,如果第 j 位为 1,则节点 node 需要进行转移到 ancestors[node][j],表示 node 向祖先方向移动了 2 j 2^{j} 2j 次。直至遍历完 k所有位或者 node 变为 −1。
时间复杂度:O(nlogn)
空间复杂度:O(nlogn)
class TreeAncestor {
static final int LOG = 16;
int[][] ancestors;
public TreeAncestor(int n, int[] parent) {
ancestors = new int[n][LOG];
for (int i = 0; i < n; i++) {
Arrays.fill(ancestors[i], -1);
}
for (int i = 0; i < n; i++) {
ancestors[i][0] = parent[i];
}
for (int j = 1; j < LOG; j++) {
for (int i = 0; i < n; i++) {
if (ancestors[i][j - 1] != -1) {
ancestors[i][j] = ancestors[ancestors[i][j - 1]][j - 1];
}
}
}
}
public int getKthAncestor(int node, int k) {
for (int j = 0; j < LOG; j++) {
if (((k >> j) & 1) != 0) {
node = ancestors[node][j];
if (node == -1) {
return -1;
}
}
}
return node;
}
}
有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~