题目

题目来源:力扣(LeetCode)

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

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

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

示例 1:
image.png
输入:root = [2,1,3]
输出:true

示例 2:
image.png
输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。

思路分析

若一棵二叉树为二叉搜索树,则有以下性质:

  1. 若任意节点的左子树不为空,则左子树上所有节点的值均小于它的根节点的值;
  2. 若任意节点的右子树不为空,则右子树上所有子节点的值均大于它的根节点的值;
  3. 任意节点的左、右子树也分别为二叉搜索树;

二叉搜索树的中序遍历顺序为: 左子树 -> 根节点 -> 右子树

结合二叉搜索树的性质,可得:二叉搜索树的中序遍历结果是一个升序序列。

因此,我们可以在中序遍历时,判断当前节点的值是否大于中序遍历的前一个节点的值,如果均大于说明这个序列是升序的,整棵树是二叉搜索树,否则不是,那么就返回false。

递归实现中序遍历

  1. /**
  2. * Definition for a binary tree node.
  3. * function TreeNode(val, left, right) {
  4. * this.val = (val===undefined ? 0 : val)
  5. * this.left = (left===undefined ? null : left)
  6. * this.right = (right===undefined ? null : right)
  7. * }
  8. */
  9. /**
  10. * @param {TreeNode} root
  11. * @return {boolean}
  12. */
  13. var isValidBST = function (root) {
  14. let pre = -Infinity
  15. return inOrder(root,)
  16. function inOrder(root) {
  17. if (root == null) {
  18. return true;
  19. }
  20. // 访问左子树
  21. if (!inOrder(root.left)) {
  22. return false;
  23. }
  24. // 访问当前节点:如果当前节点小于等于中序遍历的前一个节点,说明不满足BST,返回 false;否则继续遍历。
  25. if (root.val <= pre) {
  26. return false;
  27. }
  28. pre = root.val;
  29. // 访问右子树
  30. return inOrder(root.right);
  31. }
  32. }

栈模拟中序遍历

  1. /**
  2. * Definition for a binary tree node.
  3. * function TreeNode(val, left, right) {
  4. * this.val = (val===undefined ? 0 : val)
  5. * this.left = (left===undefined ? null : left)
  6. * this.right = (right===undefined ? null : right)
  7. * }
  8. */
  9. /**
  10. * @param {TreeNode} root
  11. * @return {boolean}
  12. */
  13. var isValidBST = function (root) {
  14. let stack = [];
  15. let inorder = -Infinity;
  16. while (stack.length || root !== null) {
  17. while (root !== null) {
  18. stack.push(root);
  19. root = root.left;
  20. }
  21. root = stack.pop();
  22. // 如果中序遍历得到的节点的值小于等于前一个 inorder,说明不是二叉搜索树
  23. if (root.val <= inorder) {
  24. return false;
  25. }
  26. inorder = root.val;
  27. root = root.right;
  28. }
  29. return true;
  30. };