BST

Closest Binary Search Tree Value

所謂 “最近的點”,可能是 parent ,可能是 child,可能在左邊,也可能在右邊。

  • 所以一要存好 prev;

  • 二要兩邊都探,不能沿着一邊硬走。

  • 爲什麼寫成兩個函數?因爲這裏是preorder traversal!

使用二叉樹的preoder traversal,不斷update closet value

public class Solution {
    double dif=Double.MAX_VALUE;
    int nodeval=0;
    
    public int closestValue(TreeNode root, double target) {
        helper(root,target);
        return nodeval;
    }
    
    private void helper(TreeNode root,double target){
        if(root==null) return;
        
        if(target==root.val){
            nodeval=root.val;
            return;
        }
        
        if(Math.abs(target-root.val)<dif){
            dif=Math.abs(target-root.val);
            nodeval=root.val;
        }
        helper(root.left,target);
        helper(root.right,target);
    }
}

方法二:利用BST的性質+BST遍歷模板(從root開始),不斷update closet value。root<target就往左走,否則就往右走。

Validate Binary Search Tree

利用 Integer 是 object 的性質,用 null reference 代表開區間。從root開始遍歷。

public class Solution {
    public boolean isValidBST(TreeNode root) {
        return isValidBST(root, null, null);
    }
    
    private boolean isValidBST(TreeNode root, Integer max, Integer min){
        if (root == null){
            return true;
        }
        // 如果該節點大於上限 返回假
        if (max != null && root.val >= max){                      //root.val是左子樹的max 右側的max是root的值,max應該比左邊要大才對
            return false;
        }
        // 如果該節點小於下限 返回假
        if (min != null && root.val <= min){                       //root.val是右子樹的value 右側的min是root的值,min應該比左邊要小纔對(min比右子樹最小的還要小)
            return false;
        }
        // 遞歸判斷左子樹和右子樹
        return isValidBST(root.left, root.val, min) && isValidBST(root.right, max, root.val);
    }
}

同樣的,這題用 in-order traversal 也可以做,也不需要設全局變量。根據inorder性質,從left most開始遍歷。後一個number起碼不小於前一個number。

public boolean isValidBST(TreeNode root) {
   if (root == null) return true;
   Stack<TreeNode> stack = new Stack<>();
   TreeNode pre = null;
   while (root != null || !stack.isEmpty()) {
      while (root != null) {
         stack.push(root);
         root = root.left;
      }
      root = stack.pop();
      if(pre != null && root.val <= pre.val) return false;
      pre = root;
      root = root.right;
   }
   return true;
}

Kth Smallest Element in a BST

這題考察的就是 BST 的性質: in order = sorted.

另一種應對多次查詢的好辦法是 augmented binary tree; 第一次用 O(n) 的時間統計記錄一下每個 node 左子樹節點個數,後面的每次查詢就可以 O(height) 的時間搜索了。

public class Solution {
    public int kthSmallest(TreeNode root, int k) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode cur = root;

        while(cur != null || !stack.isEmpty()){
            while(cur != null){
                stack.push(cur);
                cur = cur.left;
            }

            TreeNode node = stack.pop();
            if(--k == 0) return node.val;
            cur = node.right;
        }

        return root.val;
    }
}

Inorder Successor in BST

簡單寫法是 naive 的in order traversal. 只要是 binary tree 都可以用。

public class Solution {
    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode cur = root;
        boolean reachedP = false;

        while(cur != null || !stack.isEmpty()){
            while(cur != null){
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode node = stack.pop();
            if(reachedP) return node;
            if(node == p) reachedP = true;

            cur = node.right;
        }
        return null;
    }
}
  • 不過這題還可以進一步利用 BST 的性質,用模板從root開始遍歷,每一次把比p.val稍大的那個root.val給記錄下來

public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
    TreeNode res = null;
    while(root!=null) {
        if(root.val > p.val) {
            res = root;
            root = root.left;
        }
        else root = root.right;
    }
    return res;
}

Convert Sorted Array to Binary Search Tree

利用 BST inorder = sorted 的性質,一道很有意思的遞歸題。

在 BST 裏多用區間的思想思考問題。

public class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return helper(nums, 0, nums.length - 1);
    }

    private TreeNode helper(int[] nums, int start, int end){
        if(start > end) return null;
        if(start == end) return new TreeNode(nums[start]);

        int mid = start + (end - start) / 2;

        TreeNode root = new TreeNode(nums[mid]);
        root.left = helper(nums, start, mid - 1);
        root.right = helper(nums, mid + 1, end);

        return root;
    }








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章