二叉树上有
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
};