题目描述

给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:

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

思路

二叉搜索树的中序遍历。

中序遍历:左 -> 根 -> 右。
对于二叉搜索树,有左 < 根 < 右。
因此对一棵二叉搜索树进行中序遍历,一定是递增的,例如:
image.png
对如上二叉搜索树进行中序遍历,得到:
1, 2, 3, 4, 5, 6, 7, 8
因此我们对一棵二叉树进行中序遍历,如果发现当前遍历的结点的值小于上一个结点的值, 那么就不是一棵二叉搜索树。即如果:

  1. 左不小于中, 或者
  2. 中不小于右。

则不是二叉搜索树。

代码

回忆No.94, 采取递归实现中序遍历, 将其存放到一个数组中,遍历该数组,如果发现不是升序的则return false;

  1. class Solution {
  2. public boolean isValidBST(TreeNode root) {
  3. List<Integer> result = new ArrayList<>();
  4. traverse(root, result);
  5. // 判断结果数组是否递增
  6. for (int i = 0; i < result.size() - 1; i++) {
  7. if (result.get(i) >= result.get(i + 1)) {
  8. return false;
  9. }
  10. }
  11. return true;
  12. }
  13. // 与No.94完全相同
  14. private void traverse(TreeNode root, List<Integer> result) {
  15. if (root == null) {
  16. return;
  17. }
  18. traverse(root.left, result);
  19. result.add(root.val);
  20. traverse(root.right, result);
  21. }
  22. }

以上方法可以被优化,实际上不用存放到数组中,而是在遍历过程中进行大小的判断。

  1. class Solution {
  2. // 初始化前一个结点的值,默认为最小值,即最左边的结点先和最小值进行比较
  3. // 此处不用Integer.MIN_VALUE;
  4. // 因为在Leetcode中有非常极端的条件,此处不用Integer.MIN_VALUE,
  5. // 需要让第一次比较为true, 所以采用Long.MIN_VALUE;
  6. long pre = Long.MIN_VALUE;
  7. public boolean isValidBST(TreeNode root) {
  8. boolean isValid = traverse(root);
  9. return isValid;
  10. }
  11. private boolean traverse(TreeNode root) {
  12. if (root == null) {
  13. return true;
  14. }
  15. if (!traverse(root.left)) {
  16. return false;
  17. }
  18. if (root.val <= pre) {
  19. return false;
  20. }
  21. pre = root.val;
  22. return traverse(root.right);
  23. }
  24. }

TODO

对以上代码进行注释并详解。