当前位置:   article > 正文

Leetcode98 验证二叉搜索树

Leetcode98 验证二叉搜索树

题意理解:

        首先明确二叉树的定义,对于所有节点,根节点的值大于左子树所有节点的值,小于右子树所有节点的值。

注意一个误区: 

       根节点简单和左孩子,右孩子比大小是不够的,要和子树比,如下图:

       他每个节点根节点大于左孩子,小于右孩子。

       但是他的每个根节点不大于左子树的所有节点的值,小于右子树所有节点的值,它是无序的,不是一颗二叉搜索树.

二叉搜索树的特点:

        二叉搜索树的中序遍历是单调递增的数列。

1.数列递增判断【其实也是递归】

已知二叉搜索树的中序遍历的单调递增的,所以只要判断二叉树中序遍历数列是否单调递增即可。

  1. //一个合法的搜索二叉树的中序遍历应该是严格的递增数列
  2. List<Integer> reuslt=new ArrayList<>();
  3. public boolean isValidBST(TreeNode root) {
  4. if(root==null) return true;
  5. //中序遍历是递增序列
  6. //左节点处理
  7. boolean left=isValidBST(root.left);
  8. //根节点处理
  9. //数列为空的时候,直接往进加
  10. //数列不为空的时候与数列最后一位的值比大小,
  11. // 比它大则说明单调递增
  12. // 比它小则说明不符合单调递增,返回false
  13. if(reuslt.size()==0||reuslt.get(reuslt.size()-1)< root.val){
  14. reuslt.add(root.val);
  15. }else{
  16. return false;
  17. }
  18. //右节点处理
  19. boolean right=isValidBST(root.right);
  20. return left&right;
  21. }

2.递归

  1. //递归
  2. //为什么用long?
  3. //因为节点值-2^31 <= Node.val <= 2^31 - 1,囊括了int范围所有值
  4. //maxValue初始为比int最小值还小的值
  5. //故取long的最小值,long的取值范围比int更广
  6. Long maxValue=Long.MIN_VALUE;
  7. public boolean isValidBST2(TreeNode root) {
  8. if(root==null) return true;
  9. //中序遍历
  10. //左子树验证
  11. boolean left=isValidBST2(root.left);
  12. //中节点处理
  13. // maxValue总是保存当前递增的最大值
  14. // 当前值比maxValue大,则说明符合单调递增,将当前值给maxValue
  15. // 当前值比maxValue小,则说明不符合单调递增,返回false
  16. if(maxValue<root.val) maxValue=(long)root.val;
  17. else return false;
  18. //右子树验证
  19. boolean right=isValidBST2(root.right);
  20. return left&right;
  21. }

3.递归+双指针优化

把maxValue改为使用 TreeNode pre,来指向遍历的前一个节点,root总是指向当前节点,不需要复杂的考虑long还是int的问题,其余地方其实是一样的。

  1. //递归+双指针
  2. TreeNode pre=null;
  3. public boolean isValidBST3(TreeNode root) {
  4. if(root==null) return true;
  5. boolean left=isValidBST3(root.left);
  6. if(pre==null||pre.val< root.val) pre=root;
  7. else return false;
  8. boolean right=isValidBST3(root.right);
  9. return left&right;
  10. }

4.迭代

迭代还是之前遍历的套路,需要使用栈保存节点,模拟递归,会有一点麻烦。

  1. public boolean isValidBST4(TreeNode root) {
  2. if(root==null) return true;
  3. //模拟递归的栈
  4. Stack<TreeNode> stack=new Stack<>();
  5. stack.push(root);
  6. TreeNode pre=null;
  7. while(!stack.isEmpty()){
  8. TreeNode tmpRoot=stack.peek();
  9. //当前节点是否为空?
  10. if(tmpRoot!=null){
  11. //若节点不为空,则弹出当前节点
  12. //由于栈总是先进后出,故左中右节点的入栈顺序应为:右中左
  13. //为了识别中节点,在中间节点入栈后,加入一个null值,所有null值后总是中间节点,用于判断。
  14. //左右节点不为空时,入栈,所以左右节点不会引入null值
  15. stack.pop();
  16. if(tmpRoot.right!=null)stack.push(tmpRoot.right);
  17. stack.push(tmpRoot);
  18. stack.push(null);
  19. if(tmpRoot.left!=null)stack.push(tmpRoot.left);
  20. }else{
  21. //若当前节点为空,则只有可能我们是在之前的操作中引入的null值
  22. //将当前null值弹出后,取下一位进行比较
  23. //若遍历前一位节点为空或当前节点大于pre节点值,则将当前节点给pre
  24. //否则:当前节点小于pre的值,不符合单调增,返回false
  25. stack.pop();
  26. TreeNode tmp=stack.pop();
  27. if(pre==null||tmp.val>pre.val) pre=tmp;
  28. else return false;
  29. }
  30. }
  31. return true;
  32. }

5.分析

时间复杂度:

        数列递增:O(n)

        递归:O(n)

        递归+双指针:O(n)

        迭代: O(n)

空间复杂度:

        数列递增:O(n)

        递归:O(1)

        递归+双指针:O(1)

        迭代:O(n)

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号