1361 验证二叉树

给定有向图,判断是否能唯一构成一颗二叉树

典型错误思路:只根据入度判断(完美踩坑!!气死了),因为有向图中可能非联通或者存在环

正确思路:

  1. 先用DFS / BFS / 并查集判断是否是联通图
  2. 再通过边数和入度来判断即可,满足边数 = n - 1的连通图一定不存在环,一定是树
class Solution {
public:
    void DFS(int x, vector<int>& leftChild, vector<int>& rightChild, bool vis[])
    {
        if(vis[x]) return;
        vis[x] = 1;
        if(leftChild[x] != -1) DFS(leftChild[x], leftChild, rightChild, vis);
        if(rightChild[x] != -1) DFS(rightChild[x], leftChild, rightChild, vis);
    }
    
    bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
        if(n == 1) return true; // 特例,单独处理
        int indegree[n], e = 0;
        bool vis[n];
        memset(indegree, 0, sizeof(indegree));
        memset(vis, 0, sizeof(vis));
        for(int i = 0; i < n; ++i)
            if(leftChild[i] != -1 || rightChild[i] != -1)
            {
                DFS(i, leftChild, rightChild, vis);
                break; // 注意DFS一个有效的即可
            }
        for(int i = 0; i < n; ++i)
        {
            if(!vis[i]) return false; // 若还有节点未访问到则非联通
            if(leftChild[i] != -1) ++indegree[leftChild[i]], ++e;
            if(rightChild[i] != -1) ++indegree[rightChild[i]], ++e;
        }
        for(int i = 0; i < n; ++i)
            if(indegree[i] > 1) // 若入度大于1
                return false; 
        return e == n - 1; 
    }
};

他人较为优秀的思路:只用并查集,在遍历的同时判断
若有两个节点父节点相同,或者某个节点有2个以上结点指向,则直接返回
最后判断连通块的个数即可

class Solution {
public:
    static const int N = 1e4 + 7;
    int p[N];
    int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }

    bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
        for (int i = 0; i < n; i ++) p[i] = i; 
        for (int i = 0; i < n; i ++) {
            int Left = leftChild[i];
            if (Left != -1) {
                int pa = find(i), pb = find(Left);
                if (pa == pb) return false; // 祖先相同
                else {
                    if (pb == Left) 
                        p[pb] = pa;
                    else // 左孩子的父亲结点已经被修改,说明左孩子已经被别的结点修改了
                        return false;
                }
            }

            int Right = rightChild[i];
            if (Right != -1) {
                int pa = find(i), pb = find(Right);
                if (pa == pb) return false;
                else {
                    if (pb == Right) 
                        p[pb] = pa;
                    else
                        return false;
                }
            }
        }
        
        // 统计连通块个数
        int ans = 0;
        for (int i = 0; i < n; i ++) {
            if (p[i] == i) ans ++;
        }
        return ans == 1;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
平衡二叉树是一种特殊的二叉搜索树,它具有以下特点: 1. 左子树和右子树的高度差不超过 1; 2. 左子树和右子树都是平衡二叉树。 常见的平衡二叉树有 AVL 树、红黑树等。 平衡二叉树基本算法验证包括以下部分: 1. 插入节点:在插入节点时,需要保证插入后树仍然是平衡的。具体操作是:首先按照二叉搜索树的插入方法将节点插入到树中,然后从插入节点开始向上逐层检查,如果检查到某个节点不平衡,就进行旋转操作,使得该节点重新平衡。旋转操作包括左旋、右旋、左右旋和右左旋四种,具体实现可参考 AVL 树、红黑树等平衡二叉树的旋转操作; 2. 删除节点:在删除节点时,同样需要保证删除后树仍然是平衡的。具体操作是:先按照二叉搜索树的删除方法将节点删除,然后从删除节点的父节点开始向上逐层检查,如果检查到某个节点不平衡,就进行旋转操作,使得该节点重新平衡; 3. 查找节点:在平衡二叉树中查找节点的方法与二叉搜索树相同,具体操作是从根节点开始,比较待查找节点与当前节点的大小关系,然后根据比较结果向左子树或右子树遍历,直到找到目标节点或遍历到叶子节点为止。 以上就是平衡二叉树基本算法验证的内容。需要注意的是,不同的平衡二叉树可能存在一些细微的差异,具体实现时需要结合具体的平衡二叉树来进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值