1. 程式人生 > 程式設計 >LeetCode 將一個按照升序排列的有序陣列,轉換為一棵高度平衡二叉搜尋樹

LeetCode 將一個按照升序排列的有序陣列,轉換為一棵高度平衡二叉搜尋樹

第108題


將一個按照升序排列的有序陣列,轉換為一棵高度平衡二叉搜尋樹。

本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1。

示例:

給定有序陣列: [-10,-3,0,5,9],一個可能的答案是:[0,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,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(出棧)操作導致效能下降

資料