题目:
完全二叉树是每一层(除最后一层外)都是完全填充(即,节点数达到最大,第 n 层有 2n-1 个节点)的,并且所有的节点都尽可能地集中在左侧。
设计一个用完全二叉树初始化的数据结构 CBTInserter,它支持以下几种操作:
CBTInserter(TreeNode root) 使用根节点为 root 的给定树初始化该数据结构;
CBTInserter.insert(int v) 向树中插入一个新节点,节点类型为 TreeNode,值为 v 。使树保持完全二叉树的状态,并返回插入的新节点的父节点的值;
CBTInserter.get_root() 将返回树的根节点。
示例 1:
输入:inputs = ["CBTInserter","insert","get_root"], inputs = [[[1]],[2],[]]
输出:[null,1,[1,2]]
示例 2:
输入:inputs = ["CBTInserter","insert","insert","get_root"], inputs = [[[1,2,3,4,5,6]],[7],[8],[]]
输出:[null,3,4,[1,2,3,4,5,6,7,8]]
提示:
最初给定的树是完全二叉树,且包含 1 到 1000 个节点。
每个测试用例最多调用 CBTInserter.insert 操作 10000 次。
给定节点或插入节点的每个值都在 0 到 5000 之间。
代码:
package jianzhi;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class offer_43 {
// 初始化节点
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
// 队列
class CBTInserter {
// 根节点
TreeNode root;
// 初始化一个用来存储子节点未满的节点的队列
Queue<TreeNode> notFull = new LinkedList<>();
// 把子节点未满的节点放入队列
public CBTInserter(TreeNode root) {
//初始化根节点
this.root = root;
// 初始化一个队列用来存储子节点已满的队列
Queue<TreeNode> temp = new LinkedList<>();
temp.offer(root);
/**
* 1、把根节点加入队列
* 2、取出队列中的队头节点,如果子节点不满,则将此节点加入
* 3、然后依次把该节点的左右子节点加入队列
* 4、重复步骤二和步骤三,直到队列为空,此时所有不满的节点都已经加入了 notFull 队列
*/
while (!temp.isEmpty()) {
TreeNode t = temp.poll();
if (t.left == null || t.right == null) {
// 把不满的节点放入temp
notFull.offer(t);
}
if (t.left != null) {
temp.offer(t.left);
}
if (t.right != null) {
temp.offer(t.right);
}
}
}
/**
* 加入节点返回父节点的值
* 1、先查看队头节点的左子树是否为空,如果为空则把该节点加入到左子树
* 2、左子树不为空的话则把该节点加入到队头节点,此时队头节点的子节点已满,移出 notFull 队列
* @param v
* @return
*/
public int insert(int v) {
TreeNode t = notFull.peek();
if (t.left == null) {
t.left = new TreeNode(v);
notFull.offer(t.left);
} else {
t.right = new TreeNode(v);
notFull.poll();
notFull.offer(t.right);
}
return t.val;
}
public TreeNode get_root() {
return this.root;
}
}
}
解题思路:
注释写得很清楚