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;
    }








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