leetcode 1361. 验证二叉树

二叉树上有 n 个节点,按从 0 到 n - 1 编号,其中节点 i 的两个子节点分别是 leftChild[i] 和 rightChild[i]

只有 所有 节点能够形成且  形成 一颗 有效的二叉树时,返回 true;否则返回 false

如果节点 i 没有左子节点,那么 leftChild[i] 就等于 -1。右子节点也符合该规则。

注意:节点没有值,本问题中仅仅使用节点编号。


输入:n = 4, leftChild = [1,-1,3,-1], rightChild = [2,-1,-1,-1]
输出:true
/**
 * @param {number} n
 * @param {number[]} leftChild
 * @param {number[]} rightChild
 * @return {boolean}
 */
var validateBinaryTreeNodes = function (n, leftChild, rightChild) {
    //统计边数
    let edges = 0;
    //统计入度
    let nodeIn = new Array(n).fill(0);
    //统计出度
    let nodeOut = new Array(n).fill(0);
    for (let i = 0; i < n; i++) {
        if (leftChild[i] !== -1) {
            nodeIn[leftChild[i]]++;
            nodeOut[i]++;
            edges++;
        }
        if (rightChild[i] !== -1) {
            nodeIn[rightChild[i]]++;
            nodeOut[i]++;
            edges++;
        }
    };
    //如果不满足n个结点仅有n-1条边,那么说明该图不是二叉树。
    if (edges !== n - 1) {
        return false;
    }
    /**
     * 拓扑排序,判断图是否有环
     * 求出图中所有结点的出入度。
     * 将所有入度 === 0 的结点入队。
     * 当队列不空时,弹出队首元素,把与队首元素的左右子节点的入度减一。
     * 如果存在某个子节点的入度变为0,则将该结点入队。
     * 循环结束时判断已经访问的结点数,全部访问说明,图无环;存在没有访问到的结点,则有环。
     */
    let queue = [];
    let visited = new Array(n).fill(false);
    for (let i = 0; i < nodeIn.length; i++) {
        if (nodeIn[i] === 0)
            queue.push(i);
    }
    while (queue.length) {
        let node = queue.shift();
        visited[node] = true;
        if (leftChild[node] !== -1 && nodeIn[leftChild[node]] === 1) {
            nodeIn[leftChild[node]]--;
            queue.push(leftChild[node]);
        }
        if (rightChild[node] !== -1 && nodeIn[rightChild[node]] == 1) {
            nodeIn[rightChild[node]]--;
            queue.push(rightChild[node]);
        }
    }
    // 判断是否全部访问
    for (let i = 0; i < n; i++) {
        if (visited[i] === false)
            return false;
    }
    return true
};
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值