前言:20200924,某A姓世界一线大厂面试真题:
“给出一个树节点序列,判断该序列的所有节点是否在同一个二叉树上?”
面试官循循善诱,然而我当时没想到啥好的解法,直接说了个遍历每个节点数组,进行层序遍历,统计以该节点为根节点的树的节点个数。(显然复杂度很高)
以下为杂文,并不一定给出解法。
先思考子问题:如何判断一个节点node是否在某个给定的根节点为root的树上?
1.1 判断一个节点node是否在一颗根节点为root的树上?
递归即可。node在树上,则判断node是否等于tree,否则查看node是否在左右子树上。
代码如下:
bool IsNodeInTree(TreeNode* pRoot,TreeNode* pNode)
{
if(pRoot == NULL || pNode ==NULL)
return false;
if(pRoot == pNode)
return true;
if( IsNodeInTree(pRoot -> left,pNode) || IsNodeInTree(pRoot -> right,pNode) )
return true;
return false;
}
在思考:如何判断两个节点node1
和node2
是否在同一颗树上?
1.2 判断两个节点是否在同一颗树上
以
node1
和node2
表示两个节点。
- 其中一个为根节点,另一个在该树上
在1.1
中,交换顺序,互相判断即可。- 两个均为子节点,在同一颗以第三个节点
root
的树上。
如果进给此两个节点,该情况是无解的。(自动忽略)
进而思考:如何判断一颗树root1是另一个颗树的子树root2?
1.3 如何判断一颗树root1是另一个颗树的子树root2?
判断
集合
和从属关系
,不禁想起并查集unionFind
。
仔细想来,这些零星的树节点,应该构成一个图
,并且是有向图(从属关系),这部分我确实不擅长。
并查集中主要包含:初始化,路径压缩find,合并unionTwo,判断是否为统一集合isConnect 四种方法。
目前思路:先初始化并查集,随后使用1.1中方法构建表示有向图的邻接矩阵的边,即以下标为i的节点为根节点,依次判断序列中其余节点是否在该树上
。这一过程,复杂度将为N\*N\*(1.1递归的时间复杂度)
。
随后进行路径压缩find,得到每个节点所在树的根节点的编号。
…