LeetCode 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树

495 阅读2分钟

第108题


将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:

给定有序数组: [-10,-3,0,5,9],

一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:

      0
     / \
   -3   9
   /   /
 -10  5

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree

解题思路

  • 从定义我们知道,BST的中序遍历为一个递增序列,给定的数组其实就是中序遍历结果
  • 取有序数组的中间值做根,左边部分做左树,右边部分做右树如此循环迭代去二分就可还原这棵BST树

代码实现

1.二分+递归实现

每次取数组的中间值,作为二分搜索树的中间节点,依次递归下去即可

//二分+递归实现
class Solution108_1 {
    public TreeNode sortedArrayToBST(int[] nums) {
        return convertToBST(nums, 0, nums.length - 1);
    }

    TreeNode convertToBST(int[] nums, int begin, int end) {
        if (begin > end) return null;
        //取中值
        int mid = begin + (end - begin) / 2;
        TreeNode root = new TreeNode(nums[mid]);
        //左叶子树
        root.left = convertToBST(nums, begin, mid - 1);
        //右叶子树
        root.right = convertToBST(nums, mid + 1, end);
        return root;
    }
}

2.利用堆栈,去递归化实现

  • 定义一个栈,用来存将要处理数组的左索引和右索引值
  • 定义另一个栈,用来存树的节点,因为节点是先初始化,后更新节点值的迭代过程。所以需要借用堆栈先建好节点,建立好关系。
//非递归实现
class Solution108_2 {
    public TreeNode sortedArrayToBST(int[] nums) {
        if (nums == null || nums.length == 0) return null;
        Stack<Integer> stack = new Stack<Integer>();
        //数组最大索引值入栈
        stack.add(nums.length - 1);
        //数组最小索引值入栈
        stack.add(0);

        Stack<TreeNode> tree = new Stack<TreeNode>();
        TreeNode root = new TreeNode(0);
        //随便new树节点入栈
        tree.add(root);

        while (!stack.isEmpty()) {
            int left = stack.pop();
            int right = stack.pop();
            //求出中间节点索引值
            int mid = left + (right - left) / 2;
            TreeNode node = tree.pop();
            //更新根节点值
            node.val = nums[mid];

            //计算左叶子节点最大最小索引值
            int r = mid - 1, l = left;
            //如果存在左叶子节点
            if (l <= r) {
                node.left = new TreeNode(0);
                //随便new个树节点入栈
                tree.add(node.left);

                //对应右索引值入栈
                stack.push(r);
                //对应左索引值入栈
                stack.push(l);
            }

            //计算右节点最大最小索引值
            l = mid + 1;
            r = right;
            if (l <= r) {
                node.right = new TreeNode(0);
                //随便new个树节点入栈
                tree.add(node.right);

                //对应右索引值入栈
                stack.push(r);
                //对应左索引值入栈
                stack.add(l);
            }
        }
        return root;
    }
}

总结

不出所料,通过提交代码发现堆栈实现会比递归执行效率慢很多,这是因为:

  • 堆栈实现需要频繁的push(入栈)、pop(出栈)操作导致性能下降

资料