先上leetcode的题目
这道题可以直接遍历二叉树来计算节点数。但是由于题目中说了是完全二叉树,所以可以考虑优化算法,使用位运算。
整体思想
从根节点出发,每个节点只有两种走法,向左或者向右,可以联想到二进制要么为0,要么为1。
由于是完全二叉树,所以二叉树的层高h一定是最左边节点的深度。规定根节点在第0层。则第h层至少有1个节点,至多有
2
h
{2}^{h}
2h个节点。所以二叉树的节点总数最少为:
最多为:
把根节点编号为1,然后从左到右,从上往下编号。如下图是一个拥有5个节点,高度为2的完全二叉树。
每个节点的值可以用其二进制且最高位加一个1表示,比如节点5可以表示为101,然后其路径就是01。要判断节点5是否存在,只要跟着其路径判断这些节点是否存在即可。
代码如下:
public boolean exists(TreeNode root, int level, int k) {
// 此处bits是用来判断往左或者往右走的,<< 是位移符号,表示1向左移(level-1)位,右边补0
// 此时bits二进制为 010
// k 是 节点值,假设传入5,二进制为 101
int bits = 1 << (level - 1);
TreeNode node = root;
while (node != null && bits > 0) {
if ((bits & k) == 0) { // & :位运算,相等为1,不相等为0
node = node.left;
} else {
node = node.right;
}
bits >>= 1;
}
return node != null;
}
对于bit的解释,bit只在当前要查看位的值为1,所以当k这位和它相同时,就说明路径向右,否则就是向左。当比较到最后一位的时候,也就是最底层的时候,如果node存在,就说明这个节点存在,反之。