二叉树题目:在二叉树中增加一行

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法一
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法二
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:在二叉树中增加一行

出处:623. 在二叉树中增加一行

难度

5 级

题目描述

要求

给定一个二叉树的根结点 root \texttt{root} root 和两个整数 val \texttt{val} val depth \texttt{depth} depth,在给定的深度 depth \texttt{depth} depth 处添加一行值为 val \texttt{val} val 的结点。

注意,根结点 root \texttt{root} root 位于深度 1 \texttt{1} 1

添加规则如下:

  • 给定整数 depth \texttt{depth} depth,对于深度为 depth   -   1 \texttt{depth - 1} depth - 1 的每个非空树结点 cur \texttt{cur} cur,创建两个值为 val \texttt{val} val 的树结点作为 cur \texttt{cur} cur 的左子树根和右子树根。
  • cur \texttt{cur} cur 原来的左子树应该是新的左子树根的左子树。
  • cur \texttt{cur} cur 原来的右子树应该是新的右子树根的右子树。
  • 如果 depth   =   1 \texttt{depth = 1} depth = 1 意味着不存在深度 depth   -   1 \texttt{depth - 1} depth - 1,则创建一个值为 val \texttt{val} val 的树结点作为新的根结点,原始树作为新的根结点的左子树。

示例

示例 1:

二叉树题目:在二叉树中增加一行_第1张图片

输入: root   =   [4,2,6,3,1,5],   val   =   1,   depth   =   2 \texttt{root = [4,2,6,3,1,5], val = 1, depth = 2} root = [4,2,6,3,1,5], val = 1, depth = 2
输出: [4,1,1,2,null,null,6,3,1,5] \texttt{[4,1,1,2,null,null,6,3,1,5]} [4,1,1,2,null,null,6,3,1,5]

示例 2:

二叉树题目:在二叉树中增加一行_第2张图片

输入: root   =   [4,2,null,3,1],   val   =   1,   depth   =   3 \texttt{root = [4,2,null,3,1], val = 1, depth = 3} root = [4,2,null,3,1], val = 1, depth = 3
输出: [4,2,null,1,1,3,null,null,1] \texttt{[4,2,null,1,1,3,null,null,1]} [4,2,null,1,1,3,null,null,1]

数据范围

  • 树中结点数目在范围 [1,   10 4 ] \texttt{[1, 10}^\texttt{4}\texttt{]} [1, 104]
  • 树的深度在范围 [1,   10 4 ] \texttt{[1, 10}^\texttt{4}\texttt{]} [1, 104]
  • -100 ≤ Node.val ≤ 100 \texttt{-100} \le \texttt{Node.val} \le \texttt{100} -100Node.val100
  • -10 5 ≤ val ≤ 10 5 \texttt{-10}^\texttt{5} \le \texttt{val} \le \texttt{10}^\texttt{5} -105val105
  • depth \texttt{depth} depth 的最小可能值为 1 \texttt{1} 1,最大可能值为树的深度加 1 \texttt{1} 1

解法一

思路和算法

如果 depth = 1 \textit{depth} = 1 depth=1,则创建值为 val \textit{val} val 的新的根结点,将原二叉树作为新的根结点的左子树,返回新的根结点即可。

depth > 1 \textit{depth} > 1 depth>1 时,添加一行结点不会改变根结点,只要定位到添加结点的层,完成添加操作之后返回根结点即可。

根据添加规则,结点应该添加在深度 depth \textit{depth} depth 的行。令 level = depth − 1 \textit{level} = \textit{depth} - 1 level=depth1,需要定位到第 level \textit{level} level 层的全部结点,对于该层的每个结点添加两个子结点,并将原左子树和原右子树分别作为新左子结点的左子树和新右子结点的右子树。

定位到特定层添加结点可以使用深度优先搜索实现,深度优先搜索的过程中需要记录位于当前结点时应该添加在当前子树的哪一层,初始时位于根结点,层数 level = depth − 1 \textit{level} = \textit{depth} - 1 level=depth1。搜索过程中,如果 level = 1 \textit{level} = 1 level=1,则对于当前结点添加两个子结点,并将原左子树和原右子树分别作为新左子结点的左子树和新右子结点的右子树。如果 level > 1 \textit{level} > 1 level>1,则对于每个非空结点,将层数减 1 1 1 之后继续深度优先搜索。

上述过程是一个递归的过程,递归的终止条件是 level = 1 \textit{level} = 1 level=1,当 level > 1 \textit{level} > 1 level>1 时调用递归。

代码

class Solution {
    public TreeNode addOneRow(TreeNode root, int val, int depth) {
        if (depth == 1) {
            return new TreeNode(val, root, null);
        }
        insert(root, val, depth - 1);
        return root;
    }

    public void insert(TreeNode node, int val, int level) {
        TreeNode left = node.left, right = node.right;
        if (level == 1) {
            node.left = new TreeNode(val, left, null);
            node.right = new TreeNode(val, null, right);
        } else {
            if (left != null) {
                insert(left, val, level - 1);
            }
            if (right != null) {
                insert(right, val, level - 1);
            }
        }
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点最多访问一次。

  • 空间复杂度: O ( depth ) O(\textit{depth}) O(depth)。空间复杂度主要是递归调用的栈空间,栈空间的深度是 O ( depth ) O(\textit{depth}) O(depth)

解法二

思路和算法

也可以使用广度优先搜索实现,具体做法是使用层序遍历定位到添加结点的层,然后对于该层的每个结点添加两个子结点,并将原左子树和原右子树分别作为新左子结点的左子树和新右子结点的右子树。

从根结点开始依次遍历每一层的结点,在层序遍历的过程中需要记录遍历的层数,并区分不同结点所在的层,确保每一轮访问的结点为同一层的全部结点。遍历每一层结点之前首先得到当前层的结点数,即可确保每一轮访问的结点为同一层的全部结点。遍历完一层结点之后需要将层数加 1 1 1

使用队列存储待访问的结点,初始时队列中只有根结点,层数为 1 1 1。当层数等于 depth − 1 \textit{depth} - 1 depth1 时,队列中的结点即为需要添加子结点的全部结点,对于队列中的每个结点添加两个子结点,并将原左子树和原右子树分别作为新左子结点的左子树和新右子结点的右子树。

代码

class Solution {
    public TreeNode addOneRow(TreeNode root, int val, int depth) {
        if (depth == 1) {
            return new TreeNode(val, root, null);
        }
        int level = 1;
        Queue<TreeNode> queue = new ArrayDeque<TreeNode>();
        queue.offer(root);
        while (!queue.isEmpty() && level < depth - 1) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                TreeNode left = node.left, right = node.right;
                if (left != null) {
                    queue.offer(left);
                }
                if (right != null) {
                    queue.offer(right);
                }
            }
            level++;
        }
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            TreeNode left = node.left, right = node.right;
            node.left = new TreeNode(val, left, null);
            node.right = new TreeNode(val, null, right);
        }
        return root;
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点最多被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是队列空间,队列内元素个数不超过 n n n

你可能感兴趣的:(数据结构和算法,#,树,树,二叉树)