描述

给你一棵二叉搜索树,请你 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没有左子节点,只有一个右子节点。

示例

示例1:
ex1.jpg

  1. 输入:root = [5,3,6,2,4,null,8,1,null,null,null,7,9]
  2. 输出:[1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]

示例2:

ex2.jpg

输入:root = [5,1,7]
输出:[1,null,5,null,7]

提示

  • 树中节点数的取值范围是 [1, 100]
  • 0 <= Node.val <= 1000

解题思路

方法一:中序遍历之后生成新的树

  • 先对输入的二叉搜索树执行中序遍历,将结果保存到一个列表中;
  • 然后根据列表中的节点值,创建等价的只含有右节点的二叉搜索树,其过程等价于根据节点值创建一个链表。

代码

class Solution {
    List<Integer> list = new ArrayList<>();
    public TreeNode increasingBST(TreeNode root) {
        list = dfs(root);
        TreeNode first = new TreeNode(list.get(0));
        TreeNode pre = first;
        for (int i = 1; i < list.size(); i++) {
            TreeNode node = new TreeNode(list.get(i));
            pre.right = node;
            pre = node;
        }
        return first;
    }
    public List<Integer> dfs (TreeNode root) {
        if (root == null) return null;
        dfs(root.left);
        list.add(root.val);
        dfs(root.right);
        return list;
    }
}

复杂度分析

时间复杂度:O(n),其中 n 是二叉搜索树的节点总数。
空间复杂度:O(n),其中 n 是二叉搜索树的节点总数。需要长度为 n 的列表保存二叉搜索树的所有节点的值。

方法二:在中序遍历的过程中改变节点指向

当我们遍历到一个节点时,把它的左孩子设为空,并将其本身作为上一个遍历到的节点的右孩子。这里需要有一些想象能力。递归遍历的过程中,由于递归函数的调用栈保存了节点的引用,因此上述操作可以实现。

代码


class Solution {
    private TreeNode resNode;

    public TreeNode increasingBST(TreeNode root) {
        TreeNode dummyNode = new TreeNode(-1);
        resNode = dummyNode;
        inorder(root);
        return dummyNode.right;
    }

    public void inorder(TreeNode node) {
        if (node == null) {
            return;
        }
        inorder(node.left);

        // 在中序遍历的过程中修改节点指向
        resNode.right = node;
        node.left = null;
        resNode = node;

        inorder(node.right);
    }
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉搜索树的节点总数。
  • 空间复杂度:O(n)。递归过程中的栈空间开销为 O(n)。