algorighm/top-interview-leetcode150/binary-tree/222完全二叉树得节点个数.js

99 lines
3.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
const countNodes = function (root) {
};
/*
思路:以任何方式遍历一遍,统计个数
*/
function f1(root) {
let count = 0;
// 中序遍历递归函数
const inTarverse = (node) => {
// 如果root为空直接返回
if (!node) return;
// 调用左子树
inTarverse(node.left);
// 统计当前节点
count++;
// 调用右子树
inTarverse(node.right);
};
inTarverse(root);
return count;
}
/*
除了遍历所有节点统计个数,还可以利用完全二叉树个数与位置的关系通过二分查找来判断节点的个数,分为两步,
第一步:首先获得这棵完全二叉树的高度,通过高度我们可以判断一颗完全二叉树的节点数量范围[2^n, 2^n - 1]个节点
第二步:节点个数的二进制和位置右某种关系,[1,2,3],来看这个例子,首先根节点,也就是第一个节点,那么它的二进制就是
1再来看第二个2,二进制位103,位11这还不够明显再加四个数[1,2,3,4,5,6,7],4->100,5->101,6->110,7->111,这个规律就是
二进制位决定了这个节点从根节点到这个位置的路径7->111第一个1表示的是根节点第二个1表示这个节点在根节点的右子树第三个1
表示的是在更节点的右节点的右节点。
过程编写一个exists 判断指定位置的节点是否在root中存在,接收三个参数根节点root树的高度指定要判断的节点
*/
/**
*
* @param {*} root 根节点
* @param {*} h 完全二叉树的高度
* @param {*} k 最后一层的某一个节点 [2^n, 2^n - 1]
*/
const exists = (root, h, k) => {
// 初始bits位 1 << (h-1)假设h是3,那么默认值位100如果我们要查找第12个数是否存在就可以通过 1100 & 0100来
// 判断是在右子树还是在左子树
let bits = 1 << (h - 1);
let node = root;
while (bits) {
if (bits & k) { // bits&k不等于0表示这个节点应该往右子树查找
node = root.right;
} else { // 反之在左子树
node = root.left;
}
bits >>= 1;
}
// 判断node是否等于空
return node === null;
};
function f2(root) {
if (!root) return 0;
// 查找树的深度
let h = 0;
let node = root.left;
while (node) {
h++;
node = node.left;
}
// 通过树的深度计数出数量的范围 low和high
let low = 2 ** h;
let high = 2 ** (h + 1) - 1;
// 二分查找知道low===high结束查找, 以h=3来思考[815]
while (low < high) {
// 计数出中间位置
const mid = low + Math.floor((high - low) / 2);
if (exists(root, h, mid)) {
// 如果这个树存在那么节点个数大于等于这个数将左边界移动到mid
low = mid;
} else {
high = mid - 1;
}
}
// 此时low和high会相等这个位置就是二叉树的个数
return low;
}