题目

Given a binary tree, determine if it is a valid binary search tree (BST).

Assume a BST is defined as follows:

  • The left subtree of a node contains only nodes with keys less than the node’s key.
  • The right subtree of a node contains only nodes with keys greater than the node’s key.
  • Both the left and right subtrees must also be binary search trees.

Example 1:

  1. 2
  2. / \
  3. 1 3
  4. Input: [2,1,3]
  5. Output: true

Example 2:

  1. 5
  2. / \
  3. 1 4
  4. / \
  5. 3 6
  6. Input: [5,1,4,null,null,3,6]
  7. Output: false
  8. Explanation: The root node's value is 5 but its right child's value is 4.

题意

判断给定树是否为二叉查找树(左/右子树为严格小于/大于关系)。

思路

第一时间想到递归判断左结点小于根结点、右结点大于根结点,但这种做法是错误的,因为可能出现以下这种情况(因为只考虑了左子树根结点小于根节点,实际上要保证左子树所有结点都小于根节点,右子树同理):
image.png
由BST的性质-中序遍历必然得到递增序列,因而可以通过中序遍历给定二叉树,判断序列是否递增对来判断是否是BST。中序遍历方法较多,具体可参考 94. Binary Tree Inorder Traversal

另一种方法:对第一种方法进行改进,加上最小值、最大值的限定,使得当前结点都必须在(min, max)的范围里。因为测试样例包含了Integer.MAX_VALUE和Integer.MIN_VALUE,所以范围端点要使用long(硬要用int可以再设两个参数minUsed和maxUsed来标记Integer边界值是否已被使用)。


代码实现

Java

范围限制

  1. class Solution {
  2. public boolean isValidBST(TreeNode root) {
  3. return isValid(root, Long.MIN_VALUE, Long.MAX_VALUE);
  4. }
  5. private boolean isValid(TreeNode x, long minValue, long maxValue) {
  6. if (x == null) {
  7. return true;
  8. }
  9. if (x.val >= maxValue || x.val <= minValue) {
  10. return false;
  11. }
  12. return isValid(x.left, minValue, x.val) && isValid(x.right, x.val, maxValue);
  13. }
  14. }

中序遍历

  1. class Solution {
  2. int pre;
  3. boolean isFirst;
  4. public boolean isValidBST(TreeNode root) {
  5. isFirst = true;
  6. return isValid(root);
  7. }
  8. private boolean isValid(TreeNode x) {
  9. if (x == null) {
  10. return true;
  11. }
  12. // 处理左子树
  13. if (!isValid(x.left)) {
  14. return false;
  15. }
  16. // 处理当前结点
  17. if (!isFirst && x.val <= pre) {
  18. return false;
  19. }
  20. if (isFirst) {
  21. isFirst = false;
  22. }
  23. pre = x.val;
  24. // 处理右子树
  25. if (!isValid(x.right)) {
  26. return false;
  27. }
  28. return true;
  29. }
  30. }

JavaScript

  1. /**
  2. * @param {TreeNode} root
  3. * @return {boolean}
  4. */
  5. var isValidBST = function (root) {
  6. return isValid(root, [-Infinity, Infinity])
  7. }
  8. let isValid = function (root, range) {
  9. if (!root) {
  10. return true
  11. }
  12. if (root.val >= range[1] || root.val <= range[0]) {
  13. return false
  14. }
  15. return isValid(root.left, [range[0], root.val]) && isValid(root.right, [root.val, range[1]])
  16. }