leetcode树之完全二叉树

222、完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例1:

输入:root = [1,2,3,4,5,6]
输出:6

示例2:

输入:root = []
输出:0

示例3:

输入:root = [1]
输出:1

思路:

很自然想到遍历整个树,统计完全二叉树的节点数

class Solution:
    def countNodes(self, root: TreeNode) -> int:
        if not root: return 0
        queue = [root]
        total = 0
        while queue:
          	# 累加每层的节点数
            total += len(queue)
            queue = [n for node in queue for n in [node.left, node.right] if n]
        return total

也可以先计算出树的深度,这样只要找到最后一层的节点数即可,找到最后一层的节点,可以使用二分法

class Solution:
  	# 计算树的深度
    def getDepth(self, root):
        cur, dep = root, 0
        while cur.left:
            cur, dep = cur.left, dep + 1
        return dep
		# 判断位置是否有节点
    # 最后一层的结点位置为 2**depth 至 2**(depth + 1) - 1
    # 可以看到除了第一个高位外,其余位置代表着该节点在树的走向,比如11的二进制为1011,后面三位为011,那么代表着左右右节点方向
    # 这样我们可以通过按位与的方式获取当前是指向左子节点还是右子节点
    # 将当前比较的位设置为1,其他位置为0即可
    def hasNode(self, root, index, depth):
        bit = 1 << (depth - 1)
        cur = root
        while depth > 0:
            if bit & index > 0:
                cur = cur.right
            else:
                cur = cur.left
            depth -= 1
            bit = bit >> 1
        return cur != None

    def countNodes(self, root: TreeNode) -> int:
        if not root: return 0
        dep = self.getDepth(root)
        print(dep)
        start, end = 1 << dep, (1 << (dep + 1)) - 1
        # 使用二分法找到最后一个节点
        while start < end:
            mid = (start + end + 1) >> 1
            if self.hasNode(root, mid, dep):
                start = mid
            else:
                end = mid - 1
        return start
919、完全二叉树插入器

完全二叉树 是每一层(除最后一层外)都是完全填充(即,节点数达到最大)的,并且所有的节点都尽可能地集中在左侧。

设计一种算法,将一个新节点插入到一个完整的二叉树中,并在插入后保持其完整。

实现 CBTInserter 类:

  • CBTInserter(TreeNode root) 使用头节点为 root 的给定树初始化该数据结构;
  • CBTInserter.insert(int v) 向树中插入一个值为 Node.val == val的新节点 TreeNode。使树保持完全二叉树的状态,并返回插入节点 TreeNode 的父节点的值;
  • CBTInserter.get_root() 将返回树的头节点。

思路:

完全二叉树需要上一层完全填充后再插入下一层,可以通过层序遍历,记录最后已经完全填充的层,找到下一层还未填充的位置,那么插入的时候,只需要在指定位置继续填充即可。

class CBTInserter:

    def __init__(self, root: TreeNode):
        self.root = root
        # 层node队列
        self.queue = [self.root]
        self.index = 0
        while self.queue:
          	# 遍历层,找到未完全插入的下标
            for i, node in enumerate(self.queue):
                if not node.left or not node.right:
                    self.index = i
                    return
            self.queue = [n for node in self.queue for n in [node.left, node.right] if n]
		# 插入的时候,获取未插入完全插入的节点
    # 按照左子节点,右子节点的顺序插入
    # 如果是右子节点,判断是否该层已经插入完成,如果已经插入完成,更新队列为下一层结点
    def insert(self, v: int) -> int:
        cur = self.queue[self.index]
        if not cur.left:
            cur.left = TreeNode(v)
            return cur.val
        if not cur.right:
            cur.right = TreeNode(v)
            self.index += 1
            if self.index > len(self.queue) - 1:
                self.index = 0
                self.queue = [n for node in self.queue for n in [node.left, node.right] if n]
            return cur.val
		# 返回根节点
    def get_root(self) -> TreeNode:
        return self.root
958、二叉树的完全性校验

给定一个二叉树的 root ,确定它是否是一个 完全二叉树 。

在一个 完全二叉树 中,除了最后一个关卡外,所有关卡都是完全被填满的,并且最后一个关卡中的所有节点都是尽可能靠左的。它可以包含 1 到 2h 节点之间的最后一级 h 。

示例1:

输入:root = [1,2,3,4,5,6]
输出:true
解释:最后一层前的每一层都是满的(即,结点值为 {1} 和 {2,3} 的两层),且最后一层中的所有结点({4,5,6})都尽可能地向左。

示例2:

输入:root = [1,2,3,4,5,null,7]
输出:false
解释:值为 7 的结点没有尽可能靠向左侧。

思路:

由于完全二叉树的特点,除了最后一层,前面层的节点都是填满的,可以使用层序遍历,如果发现层有空节点,并且空节点之后又有不为空的节点,说明此时该层的数据不是满的

class Solution:
    def isCompleteTree(self, root: TreeNode) -> bool:
        if not root: return True
        queue = [root]
        # 标记是否有空节点
        hasNone = False
        while queue:
            for i in range(len(queue)):
                cur = queue.pop(0)
                # 如果有空节点进行标记
                if not cur:
                    hasNone=True
                    continue
                # 如果已经标记有空节点,但是却发现还有新的不为空的节点,说明不是完全二叉树,返回False
                if hasNone: return False
                queue.append(cur.left)
                queue.append(cur.right)
        # 遍历完成后,说明是完全二叉树
        return True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

溪语流沙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值