验证二叉搜索树

题目描述

力扣链接🔗

验证二叉搜索树 - 图1

代码分析

数组法

大体思路为:将根据中序遍历将二叉搜索树的所有节点遍历在集合中,再判断集合是否递增即可。但数组法的时间复杂度为O(n ^ n)。

  1. /**
  2. * 解法一:中序遍历获得一个数组,判断数组是否升序
  3. *
  4. * @param root
  5. * @return
  6. */
  7. List<Integer> res = new ArrayList<>();
  8. public boolean isValidBST(TreeNode root) {
  9. traversal(root);
  10. // 对集合进行判断
  11. for (int i = 1; i < res.size(); i++) {
  12. if (res.get(i) <= res.get(i - 1)) { // 二叉搜索树不能相等
  13. return false;
  14. }
  15. }
  16. return true;
  17. }
  18. public TreeNode traversal(TreeNode root) {
  19. if (root == null) {
  20. return null;
  21. }
  22. if (root.left != null) traversal(root.left);
  23. res.add(root.val);
  24. if (root.right != null) traversal(root.right);
  25. return root;
  26. }

递归法

大坑:不能单纯的判断左边小于中间,右边大于中间,搜索二叉树是左边所有节点小于中间节点,右边所有节点大于中间节点。

例如:

  1. if (root->val > root->left->val && root->val < root->right->val) {
  2. return true;
  3. } else {
  4. return false;
  5. }

以上就是错误代码,无法解决这种情况。

验证二叉搜索树 - 图2

还有一个坑,样例中最小节点 可能是int的最小值,如果这样使用最小的int来比较也是不行的。所以优化后将最左边的值存到变量中,此时就没有比最左边的值更小的值。

  1. 确定返回值和参数
    由于时返回当前是否为二叉搜索树,所以不需要全部遍历,所以返回值为boolean
  2. 终止递归条件
    由于搜索二叉树可以为空,所以为空时返回true
  3. 处理每层的逻辑
    中序遍历,一直更新maxVal,一旦发现maxVal >= root->val,就返回false,注意元素相同时候也要返回false。
  1. /**
  2. * 递归法
  3. *
  4. * @param root
  5. * @return
  6. */
  7. TreeNode pre = null; // 用来记录前一个节点的值,注意需要设置为null,不能new,会默认将val设置为0,此时0的情况会判断为false
  8. public boolean isValidBST(TreeNode root) {
  9. if (root == null) { // 当为空时也为二叉搜索树
  10. return true;
  11. }
  12. boolean left = isValidBST(root.left);// 左
  13. if (pre != null && pre.val >= root.val) return false; // 右
  14. pre = root; // 获取上一个节点
  15. boolean right = isValidBST(root.right);// 右
  16. return left && right; // 判断左右是否为二叉搜索树
  17. }
  18. }

迭代法

迭代法的思路:还是利用了中序遍历的思路,再中间处理一下节点即可,判断方法和递归一致。

  1. /**
  2. * 迭代法(中序)
  3. *
  4. * @param root
  5. * @return
  6. */
  7. public boolean isValidBST(TreeNode root) {
  8. TreeNode pre = null; // 用来记录前一个节点
  9. TreeNode cur = root; // 用来记录前一个节点
  10. Stack<TreeNode> stack = new Stack<>();
  11. while (cur != null || !stack.isEmpty()) {
  12. if (cur != null) {
  13. stack.push(cur);
  14. cur = cur.left; // 一直将左孩子入栈
  15. } else {
  16. cur = stack.pop();// 左孩子为空时
  17. if (pre != null && pre.val >= cur.val) return false;
  18. pre = cur;
  19. cur = cur.right;
  20. }
  21. }
  22. return true;
  23. }