zoukankan      html  css  js  c++  java
  • LeetCode 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树

    第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(出栈)操作导致性能下降

    资料

  • 相关阅读:
    CTO成长之路分享会
    MySQL 数据库 varchar 到底可以存多少个汉字,多少个英文呢?我们来搞搞清楚
    《共享经济》创业沙龙
    旅游代购
    沙漏哟的书单
    qt5---滑动条QSlider
    qt5---步长调节器SpinBox和QDoubleSpinBox
    qt5--自定义控件封装
    qt5--表格控件QTableWidget
    qt5--树形控件QTreeWidget
  • 原文地址:https://www.cnblogs.com/tqlin/p/11593964.html
Copyright © 2011-2022 走看看