题目:
完全二叉树是每一层(除最后一层外)都是完全填充(即,节点数达到最大,第 n 层有 2^n-1 个节点)的,并且所有的节点都尽可能地集中在左侧。
设计一个用完全二叉树初始化的数据结构 CBTInserter,它支持以下几种操作:
CBTInserter(TreeNode root) 使用根节点为 root 的给定树初始化该数据结构;
CBTInserter.insert(int v) 向树中插入一个新节点,节点类型为 TreeNode,值为 v 。使树保持完全二叉树的状态,并返回插入的新节点的父节点的值;
CBTInserter.get_root() 将返回树的根节点
分析:
如上图,完全二叉树插入节点7,8,9,观察到插入顺序满足广度优先遍历,数据结构可以采用队列,从根节点开始广度优先遍历,先入队根节点,当一个节点既有左节点又有右节点时,出队该节点,并入队该节点的左节点和该节点的右节点,根据这种规律以此类推,例如a,1出队,2,3入队,2有左右节点,所以2出队,4,5入队,因此队列中存在5,4,3节点,节点6还未添加到队列中。
当插入节点7时,节点3正好位于队头,3已经有左节点了,因此新的节点插入它右子节点的位置,插入节点7后,3节点左节点和右节点就都存在了,因此出队3,入队6,7,后面的插入步骤同理。
根据广度优先搜索的顺序找出二叉树中所有既有左子节点又有右子节点的节点,因此时间复杂度O(n)。空间复杂度也为O(n)。
代码:
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;
}
}
import java.util.LinkedList;
import java.util.Queue;
public class CBTInserter {
private Queue<TreeNode> queue;
private TreeNode root;
public CBTInserter(TreeNode root) {
this.root = root;
queue = new LinkedList<>();
queue.offer(root);
while (queue.peek().left !=null && queue.peek().right !=null){
TreeNode node = queue.poll();
queue.offer(node.left);
queue.offer(node.right);
}
}
public int insert(int v) {
TreeNode parent = queue.peek();
TreeNode node = new TreeNode(v);
if (parent.left == null){
parent.left = node;
}else {
parent.right = node;
queue.poll();
queue.offer(parent.left);
queue.offer(parent.right);
}
return parent.val;
}
public TreeNode get_root() {
return this.root;
}
}