1. 程式人生 > >Leetcode __108. 將有序陣列轉換為二叉搜尋樹

Leetcode __108. 將有序陣列轉換為二叉搜尋樹

問題描述

將一個按照升序排列的有序陣列,轉換為一棵高度平衡二叉搜尋樹。
本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1

示例:
給定有序陣列: [-10,-3,0,5,9],
一個可能的答案是:[0,-3,9,-10,null,5],它可以表示下面這個高度平衡二叉搜尋樹:

      0
     / \
   -3   9
   /   /
 -10  5

思路

先理解幾個概念:
平衡二叉樹:是一種二叉排序樹,其中每一個節點的左子樹和右子樹的高度差至多等於1.
二叉搜尋樹:(二叉排序樹)又稱二叉查詢樹,它或者是一棵空樹,或者具有一下性質的二叉樹

  • 若它的左子樹不空,則左子樹上的所有節點的值均小於它的根節點的值
  • 若它的右子樹不空,則右子樹上的所有節點的值均大於它根節點的值
  • 它的左右子樹也分別為二叉排序樹
    當對一棵二叉搜尋數進行中序遍歷的時候,就可以得到一個有序的序列,這樣的數稱為二叉排序或搜尋樹
    構造一棵二叉排序或搜尋樹的目的,並不是為了排序,而是為了提高查詢和插入刪除關鍵字的速度。

從概念中可以理解出:有序序列的中間值即為根節點,左右兩邊陣列各自成二叉搜尋樹,遞迴是最簡單的實現方式

實現

/**
 1. Definition for a binary tree node.
 2. public class TreeNode {
 3.     int val;
 4.     TreeNode left;
 5.     TreeNode right;
 6.     TreeNode(int x) { val = x; }
 7. }
 */
class Solution { public TreeNode sortedArrayToBST(int[] nums) { if (nums == null || nums.length == 0) { return null; } return creatSub(nums, 0, nums.length-1); } private static TreeNode creatSub(int[] nums,int start,int end){ int len = nums.length; if
(start > end) { return null; } int rootnum = (start + end) / 2; TreeNode root = new TreeNode(nums[rootnum]);//注意是中間是陣列的值,不是排序位置 root.left = creatSub(nums, start, rootnum-1);//遞迴,要傳入變數值 root.right = creatSub(nums, rootnum + 1, end); return root; } }

犯錯

  1. 在遞迴時候思路還停留在迴圈中,思路不清晰;
  2. 邊界值處理不好,第一次傳入從0開始到長度-1結束,若不-1,則越界;
  3. 建立根節點時候,要傳入的 是中間陣列的值,不是位置;
  4. 遞迴要傳入變數,不能是具體的值;
  5. 每次遞迴呼叫子方法的時候,要把中間值根節點的值去掉,故rootnum-1,rootnum+1

實現2(不推薦)

從思路中我們知道,每次把中間根節點拋開,左右兩邊各自陣列再遞迴呼叫函式即可,但這其中要複製陣列,佔用空間較多,比較慢,

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode sortedArrayToBST(int[] nums){
        if (nums == null || nums.length == 0) {
            return null;
        }

        int len = nums.length;
        TreeNode root = new TreeNode(nums[len / 2]);
        int[] leftnum = new int[len / 2];
        int[] rightnum =new int[len - len / 2 - 1];
        System.arraycopy(nums,0,leftnum,0,len/2);
        System.arraycopy(nums,len/2+1,rightnum,0,len - len / 2 - 1);

        root.left = sortedArrayToBST(leftnum);
        root.right = sortedArrayToBST(rightnum);
        return root;

    }
}

這裡copy陣列時候用了native方法,可以比賦值陣列快一些

小結

本問題考察的就是二分查詢,每次取中間值,再對各自邊陣列遞迴,但不一樣的是,取的中間值,是中間陣列的值,記住這點即可。