算法通关村——二分查找在二叉树中的应用

1. 二叉搜索树中的搜索

二叉搜索树中的搜索
给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。

1.1 递归

一开始以为很难,无从下手,但是题目已经规定了这是二叉搜索树,意味着将元素按照中序排列,就是一个有序的数组/链表,寻找目标val,有三种结果:

  1. 等于val,那么直接输出根节点
  2. 小于val,目标val在当前节点左边
  3. 大于val,目标在val右边
    public TreeNode searchBST(TreeNode root, int val) {
        if(root==null || val == root.val) return root;
        return val<root.val ? searchBST(root.left,val) : searchBST(root.right,val);
    }

1.2 迭代

思路都是一样的

 public TreeNode searchBST(TreeNode root, int val) {
       while(root!=null && val!=root.val){
          root= val< root.val?root.left:root.right;
       }
       return root;
    }

2. 验证二叉搜索树

98. 验证二叉搜索树
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。

2.1 递归

官方的递归是重写了一个方法,先定义两个值,分别是最小的Integer和最大的Integer,那么这个节点的值一定是在这个范围内的,然后递归将子树的值分别和最小和最大的值比较,然后返回,只不过优点麻烦。
这里可以采取一个简便方法,将最小值先定义在外面,然后先对左子树递归调用 isValidBST,再判断当前节点值是否大于中序遍历的前一个节点的值,如果不大于,则返回 false,即不满足 BST 的条件。最后将当前节点的值赋给 pre 变量,并对右子树递归调用 isValidBST。

class Solution {
    // 里面会采用integer的最大值,会不通过
    long pre = Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
       if(root == null) return true;
       // 左子树元素不满足
       if(!isValidBST(root.left)){
           return false;
       }
        // 当前节点小于等于中序遍历的前一个节点
       if(root.val<= pre){
           return false;
       }
       pre = root.val;
       return isValidBST(root.right);
    }
}

2.2 迭代

二叉搜索树的中序遍历,如果能够满足条件,那么就是有序的,只需要判断当前的值是否小于之前节点的值。

    public boolean isValidBST(TreeNode root) {
       Deque<TreeNode> stack = new LinkedList<>();
       // 存储前一个节点元素值
       double inorder = -Double.MAX_VALUE;
        while(!stack.isEmpty() || root!=null){
            while(root!=null){
                stack.push(root);
                root=root.left;
            }
            root = stack.pop();
            if(root.val<=inorder){
                return false;
            }
            inorder = root.val;
            root=root.right;
        }
        return true;
    }

3. 二叉搜索树的最小绝对差

二叉搜索树的最小绝对差

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。

3.1 递归

依然是先保留前一个节点的值,然后进行中序遍历,比较前一个值与当前值的差是否小于最小值,小于就替换。

class Solution {
    // 上一个节点的值
    int pre;
    // 结果
    int ans;
    public int getMinimumDifference(TreeNode root) {
      ans = Integer.MAX_VALUE;
      pre=-1;
        dfs(root);
        return ans;
    }

    public void dfs(TreeNode root){
        if(root==null){
            return;
        }
        // 左
        dfs(root.left);
        // 中
        if(pre == -1){
            pre = root.val;
        }else{
            ans = Math.min(ans,root.val-pre);
            pre=root.val;
        }
        // 右
        dfs(root.right);
    }
}

3.2 迭代,中序遍历

一开始就是想的迭代法,但是轮到自己做就有点绕,尤其是在类里定义变量,然后方法里面使用,做法都差不多。

class Solution {
    // 记录前一个节点
    TreeNode pre;
    Stack<TreeNode> stack;
    public int getMinimumDifference(TreeNode root) {
     if(root==null) return 0;
     TreeNode cur = root;
     stack = new Stack<>();
     int res = Integer.MAX_VALUE;
     while(cur!=null || !stack.isEmpty()){
         // 当前节点不为空
         if(cur!=null){
             stack.push(cur);
             // 左
             cur=cur.left;
             // 当前节点为空
         }else{
             cur=stack.pop();
             // 中
             if(pre!=null){
                 res=Math.min(res,cur.val-pre.val);
             }
             pre=cur;
             // 右
             cur=cur.right;
         }
     }

     return res;
    }
}

你可能感兴趣的:(算法)