LC98-中-验证二叉搜索树

1 题目

https://leetcode.cn/problems/validate-binary-search-tree/description/

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含 小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

在这里插入图片描述

在这里插入图片描述

2 思路(错误)

根据上面的规则,递归判断
当出现不满足条件的节点,则返回false
当遍历所有的节点后,没有出现false的情况,则为true
注意:递归时的返回值

class Solution{
	
	public boolean isValidBST(TreeNode root) {
		if (root == null) return true;
        boolean result = true;
        if (root.left != null) result = root.left.val < root.val;
        if (root.right != null) result = root.val < root.right.val;
        if (!result) return result;

        result = isValidBST(root.left);
        if (!result) return result;
        result = isValidBST(root.right);
        if (!result) return result;
        return true;
	}
	
}

BUG1

逐个比较的问题,不能比较整个子树;当右子树中出现不合法的情况查不出来
在这里插入图片描述

10 5 null null 15 6 null null 20
正确答案: false
程序结果: true

FIX1 中序递归

二叉搜索树的先验知识:中序遍历二叉搜索树,这个序列为递增序列

知道这点后,可以获取中序遍历的序列,检测其是否递增即可

对于上面的代码如何改进?
采用中序遍历的方式,检测元素是否递增

class Solution {
    private long maxVal = Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        boolean left = isValidBST(root.left);
        if (!left) return false;
        // 检测中序元素是否递增
        if (maxVal < root.val) maxVal = root.val;
        else return false;
        boolean right = isValidBST(root.right);
        if (!right) return false;
        return true;
    }
}

小问题:
样例中最小节点可能是int的最小值,会比较出错;此时可以初始化比较元素为long的最小值。

FIX2 遍历

获取序列,检测是否递增

class Solution {
    public boolean isValidBST(TreeNode root) {
        List<Integer> numList = new LinkedList<>();
        inorderBST(root, numList);
        for (int i = 0; i < numList.size() - 1; i++) {
            if (numList.get(i) >= numList.get(i+1)) return false;
        }
        return true;
    }

    private void inorderBST(TreeNode root, List<Integer> numList) {
        if (root != null) {
            inorderBST(root.left, numList);
            numList.add(root.val);
            inorderBST(root.right, numList);
        }
    }

}

遍历的方式最慢,因为要彻底遍历整个树;对于递归的情况,如果遇到不满足的情况就即刻返回了,不会遍历整个树;

在这里插入图片描述

FIX3 中序遍历中使用prev指针

class Solution {

    private TreeNode prev = null;
    public boolean isValidBST(TreeNode root) {
        if (root != null) {
            boolean leftResult = isValidBST(root.left);
            if (!leftResult) return false;  // 提前返回

            if (prev != null) {
                if (prev.val >= root.val) return false;
            }
            prev = root;

            boolean rightResult = isValidBST(root.right);
            if (!rightResult) return false;
            // 全部扫描完成
            return true;
        }
       	// 空的二叉树也返回true
        return true;
    }
}

Note:
二叉树全局扫描还是局部扫描?

在判断BST的过程中,如果局部出现不合规的情况,就说明整体不合规,因此不需要全局扫描,所以要提前进行返回,返回false。如果全局都扫描了,没有发现不合规的情况,此时返回true;

因此判断二叉搜索树是局部扫描和全局扫描的结合

不合规的情况提前返回

...
if (leftResult == false) return false; 
...
if (rightResult == false) return false;

全部扫描完成,返回true


if (root != null) {
	// left
	// right
	// 所有的扫描完成
	return true;
}

ACM输入输出

import java.util.*;

class TreeNode{

    int val;
    TreeNode left;
    TreeNode right;
    public TreeNode() {}
    public TreeNode(int val) {this.val = val; }
}

// solution 

public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Solution solution = new Solution();
        while (in.hasNext()) {

            String[] strNums = in.nextLine().split(" ");
            List<TreeNode> nodes = new LinkedList<>();
            for (String strNum: strNums) {
                if (!strNum.isEmpty()) {
                    if (strNum.equals("null")) {
                        nodes.add(null);
                    } else {
                        nodes.add(new TreeNode(Integer.parseInt(strNum)));
                    }
                }
            }

            TreeNode root = constructTree(nodes);

            boolean r = solution.isValidBST(root);

            System.out.println(r);

        }

    }

    public static TreeNode constructTree(List<TreeNode> nodes) {
        if (!nodes.isEmpty()) {
            TreeNode node = nodes.remove(0);
            if (node != null) {
                node.left = constructTree(nodes);
                node.right = constructTree(nodes);
            }
            return node;
        }
        return null;
    }
}


参考

https://www.programmercarl.com/0098.验证二叉搜索树.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值