先写一个辅助函数bool hasK(TreeNode* root, int K)
,表示判断在一个完全二叉树里面是否存在第k号节点。这里,对于完全二叉树节点的编号规则,是按照层级遍历的顺序(如题目的图例)。hasK函数的算法思想是:对于任何编号为K的节点,我们都可以写出它从下往上(直至root)的path(就是将K不断除以2)。然后将这个path逆向,起点变成从root开始从上往下遍历,就可以查看是否能抵达编号为K的节点。
有了这个辅助函数,我们就可以利用二分搜索的思想,猜测二叉树里面是否存在编号为K的节点。如果存在,那么说明总节点数可以大于等于K;如果不存在,那么说明总节点数一定小于K。不断调整搜索范围直至收敛。
需要观察得到如下的重要性质:对于一个完全二叉树,root的左子树和右子树里面,必然有一个是满二叉树。
对于高度为h的满二叉树,其节点个数可以直接计算为2^h-1。所以我们对于root,先判断左子树是否是一个满二叉树。如果不是的话,递归处理左子树,否则就递归处理右子树。如何判断一棵树是否为满二叉树呢?只要递归计算它的左深度和有深度,查看两者是否相等就行了。
这个总算法复杂度是logN*logN。可以这么考虑:每次计算满二叉树的高度需要o(logN),不停二分递归处理非满二叉树又需要o(logN)次。
对于每一棵子树,只要考察它左子树的“左深度”h1、右子树的“左深度”h2.如果二者相等,那么递归处理右子树,即count(node) = 2^h1-1+1+count(node->right)
,否则就递归处理左子树count(node) = 2^h2-1+1+count(node->left)