首页 > 其他分享 >每日一题:1483. 树节点的第 K 个祖先

每日一题:1483. 树节点的第 K 个祖先

时间:2024-04-06 14:56:42浏览次数:12  
标签:node 祖先 1483 int pa TreeAncestor getKthAncestor 节点

给你一棵树,树上有 n 个节点,按从 0 到 n-1 编号。树以父节点数组的形式给出,其中 parent[i] 是节点 i 的父节点。树的根节点是编号为 0 的节点。

树节点的第 k 个祖先节点是从该节点到根节点路径上的第 k 个节点。

实现 TreeAncestor 类:

  • TreeAncestor(int n, int[] parent) 对树和父数组中的节点数初始化对象。
  • getKthAncestor(int node, int k) 返回节点 node 的第 k 个祖先节点。如果不存在这样的祖先节点,返回 -1 。

 

示例 1:

输入:
["TreeAncestor","getKthAncestor","getKthAncestor","getKthAncestor"]
[[7,[-1,0,0,1,1,2,2]],[3,1],[5,2],[6,3]]

输出:
[null,1,0,-1]

解释:
TreeAncestor treeAncestor = new TreeAncestor(7, [-1, 0, 0, 1, 1, 2, 2]);

treeAncestor.getKthAncestor(3, 1);  // 返回 1 ,它是 3 的父节点
treeAncestor.getKthAncestor(5, 2);  // 返回 0 ,它是 5 的祖父节点
treeAncestor.getKthAncestor(6, 3);  // 返回 -1 因为不存在满足要求的祖先节点

 

思路:开始以为很简单,只要在parent数组上不停回溯就好了,但最终在n=5000时超时了……

class TreeAncestor {
public:
    vector<int> p;
    TreeAncestor(int n, vector<int>& parent) {
        p.resize(n);
        for(int i=0;i<n;i++){
            p[i]=parent[i];
        }
    }
    
    int getKthAncestor(int node, int k) {
        for(int i=1;i<=k;i++){
            if(p[node]!=-1)node=p[node];
            else return -1;
        }
        return node;
    }
};

超时原因是每次只能一步一步跳,如果能优化成一次跳两步或是四步,就能快很多了,而如何维护一个节点的第2i个节点呢?这里用一个新学到的倍增(Binary Lifting)的方法:

class TreeAncestor {
    vector<vector<int>> pa;
public:
    TreeAncestor(int n, vector<int> &parent) {
        int m = 32 - __builtin_clz(n); // n 的二进制长度
        pa.resize(n, vector<int>(m, -1));
        for (int i = 0; i < n; i++)
            pa[i][0] = parent[i];
        for (int i = 0; i < m - 1; i++)
            for (int x = 0; x < n; x++)
                if (int p = pa[x][i]; p != -1)
                    pa[x][i + 1] = pa[p][i];                //eg:若x的第2个祖先节点是p,则p的第2个祖先节点是x的第4个祖先节点
    }

    int getKthAncestor(int node, int k) {
        int m = 32 - __builtin_clz(k); // k 的二进制长度
        for (int i = 0; i < m; i++) {
            if ((k >> i) & 1) { // k 的二进制从低到高第 i 位是 1
                node = pa[node][i];
                if (node < 0) break;
            }
        }
        return node;
    }

    // 另一种写法,不断去掉 k 的最低位的 1
    int getKthAncestor2(int node, int k) {
        for (; k && node != -1; k &= k - 1) // 也可以写成 ~node
            node = pa[node][__builtin_ctz(k)];
        return node;
    }
};

作者:灵茶山艾府
链接:https://leetcode.cn/problems/kth-ancestor-of-a-tree-node/solutions/2305895/mo-ban-jiang-jie-shu-shang-bei-zeng-suan-v3rw/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

标签:node,祖先,1483,int,pa,TreeAncestor,getKthAncestor,节点
From: https://www.cnblogs.com/Liubox/p/18117435

相关文章

  • 9. 景区导游-树上前缀和&&最近公共祖先
    9.景区导游-蓝桥云课(lanqiao.cn)641211313423524632651#include<bits/stdc++.h>#defineintlonglong#defineendl'\n'usingnamespacestd;//tu动态数组用来存图,相当于一条绳子上面有好几个结,每个结都各自连了一条链子//vector<pair<t......
  • 中间件 ZK分布式专题与Dubbo微服务入门 7-3 zk命名空间以及创建节点
    0课程地址https://coding.imooc.com/lesson/201.html#mid=12732 1重点关注1.1本节内容使用curator递归创建节点 1.2关键代码//creatingParentsIfNeeded递归创建节点//withMode节点类型,永久or临时//withACL权限anyworld//path路......
  • 每日一题:1026. 节点与其祖先之间的最大差值
    给定二叉树的根节点 root,找出存在于 不同 节点 A 和 B 之间的最大值 V,其中 V=|A.val-B.val|,且 A 是 B 的祖先。(如果A的任何子节点之一为B,或者A的任何子节点是B的祖先,那么我们认为A是B的祖先) 示例1:输入:root=[8,3,10,1,6,null,14,null,null,4,......
  • 拓扑排序--有向无环图中一个节点的所有祖先
    题目描述给你一个正整数 n ,它表示一个 有向无环图 中节点的数目,节点编号为 0 到 n-1 (包括两者)。给你一个二维整数数组 edges ,其中 edges[i]=[fromi,toi] 表示图中一条从 fromi 到 toi 的单向边。请你返回一个数组 answer,其中 answer[i]是第 i 个节......
  • P8025 【树链剖分求祖先】
    P8025【树链剖分求祖先】这题的题意简单,简单分类讨论一下这里就不赘述了。最后题目就简化成求一个点的\(k\)级祖先。开始会的解法是倍增,但是常数过高被卡了。常数更优秀的做法是树剖,每一次跳树链,最后可能有一条链太长只能跳一部分,这是因为树链剖分的\(dfn\)序是有序的,即每......
  • 删除二叉搜索树中的节点(力扣450)
    文章目录题目前知二叉搜索树是什么?题解一、思路二、解题方法三、Code总结题目Problem:450.删除二叉搜索树中的节点给定一个二叉搜索树的根节点root和一个值key,删除二叉搜索树中的key对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新......
  • 多种方法从尾部移除指定位置的链表节点
    连绵的春雨把人困在家乡,于是我继续开始刷着算法题,通过19.Remove年thNodeFromEndofList复习了一波链表的操作,这道题也是比较典型的链表问题,值得分享一下。题目如下所示:Giventheheadofalinkedlist,removethenthnodefromtheendofthelistandreturnitsh......
  • 每日一题: 2192. 有向无环图中一个节点的所有祖先
    给你一个正整数 n ,它表示一个 有向无环图 中节点的数目,节点编号为 0 到 n-1 (包括两者)。给你一个二维整数数组 edges ,其中 edges[i]=[fromi,toi] 表示图中一条从 fromi 到 toi 的单向边。请你返回一个数组 answer,其中 answer[i]是第 i 个节点的所有 祖......
  • 代码随想录算法训练营第二十一天| 530. 二叉搜索树的最小绝对差 501. 二叉搜索树中的
    530.二叉搜索树的最小绝对差https://leetcode.cn/problems/minimum-absolute-difference-in-bst/description/TreeNodepre=null;intres=Integer.MAX_VALUE;publicintgetMinimumDifference(TreeNoderoot){if(root==null)return0;pr......
  • leetcode每日一题 1379. 找出克隆二叉树中的相同节点
    问题描述给你两棵二叉树,原始树original和克隆树cloned,以及一个位于原始树original中的目标节点target。其中,克隆树cloned是原始树original的一个副本。请找出在树cloned中,与target相同的节点,并返回对该节点的引用(在C/C++等有指针的语言中返回节点指针,其他......