-
二叉树我最近刷的特别多,差不多快刷完了,但是有一种题型差点给我忽略了,那就是完全二叉树,这也是一个很重要的题型,今天刚好有一道题目可以来复习一下完全二叉树的特性
-
题目链接如下:https://leetcode.cn/problems/count-complete-tree-nodes/?envType=study-plan-v2&envId=top-interview-150
-
做这道题首先有一点要知道的,就是完全二叉树是怎么样子的,下面说一下完全二叉树的概念
-
完全二叉树:只有最底层的节点未被填满,且最底层节点尽量靠左填充
-
ok 现在已经了解了基础概念了,我们再来看这道题目
-
这道题目的目的是让我们遍历这棵树,并算有几个节点
-
说实话,这道题很简单,用暴力的做法,就是遍历一整棵树,代码如下:
-
递归法:
//方法一:递归
func Solution222(root *TreeNode) int {
if root == nil {
return 0
}
left := Solution222(root.Left)
right := Solution222(root.Right)
return left + right + 1
}
- 迭代法:
//方法二:迭代
func Solution222v2(root *TreeNode) int {
if root == nil{
return 0
}
queue := []*TreeNode{root}
count := 0
for len(queue) > 0{
node := queue[0]
queue = queue[1:]
count++
if node.Left != nil{
queue = append(queue, node.Left)
}
if node.Right != nil{
queue = append(queue, node.Right)
}
}
return count
}
-
这两个方法是遍历树的最基本的方法之一
-
但是 这不是这道题的本意,这道题目是想要我们理由完全二叉树这个特性解题
-
那我们需要好好思考一下,完全二叉树有什么特点
-
除了最后的叶子节点,其他层级节点都是满的
-
当 左子树的深度 和 右子树的深度 一致的时候,说明 左子树是满的二叉树 可以通过 2的h次方求的左子树的节点个数
-
当 右子树的深度 不如 左子树的深度 的时候,说明 左子树不是一个满的二叉树,但是右子树单独看是一个满的二叉树,所以可以通过 2的h次方求右子树的节点个数
-
-
ok,知道这些特点,我们是不是可以利用一个逻辑来减少遍历
- 当 左子树深度 等于 右子树的时候,就可以通过深度来计算左子树的节点,然后只遍历右子树
- 当 左子树深度 等于 右子树的时候,就可以通过深度来计算右子树的节点,然后只遍历左子树
-
这样我们本来需要遍历全部二叉树节点的,现在只需要遍历一半,思路瞬间打开,代码如下:
//方法三:二分查找
func Solution222v3(root *TreeNode) int {
if root == nil{
return 0
}
//检索左子树深度
left := root.Left
ldepth := 0
for left != nil{
left = left.Left
ldepth++
}
//检索右子树深度
right := root.Right
rdepth := 0
for right != nil{
right = right.Left
rdepth++
}
//左右子树深度判断
if ldepth == rdepth{
return (1<<ldepth) + Solution222v3(root.Right)
}else{
return (1<<rdepth) + Solution222v3(root.Left)
}
}
ok,这里这道题目就结束了,感谢大家观看