Leet Code 第八天——255. 验证前序遍历序列二叉搜索树

这个题说实话我确实没咋看懂啥意思,可能是因为自己对于搜索二叉树还不够熟悉。
题目:
在这里插入图片描述

看了答案,大致代码如下:

class Solution {
    public boolean verifyPreorder(int[] preorder) {
        Stack<Integer> stack = new Stack<>();
        Integer i1 = Integer.MIN_VALUE;
        for (int i = 0; i < preorder.length; i++) {
            if (preorder[i] < i1){
                return false;
            }
            while (!stack.isEmpty() && preorder[i] > stack.peek()){
                i1 = stack.pop();
            }
            stack.push(preorder[i]);
        }
        return true;
    }
}

我感觉这个题目考察的是对于搜索二叉树的一些性质问题,在开始的时候我还在想连树的根节点都没给我该怎么判断。对于搜索二叉树有以下性质;

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树
    所以我初始的想法是使用递归,但是发现行不通,最后想着这个数组应该是先单调递减然后单调递增的,结果还是错误。只想对了一半,因为只有前半部分在前序遍历时是单调递减的。而当遇到第一个大于当前值的值时,说明此时树已经遍历见底了,已经到了右子树上,那么值肯定会比当前值大,但右子树的值还可能出现变小的情况,只要这些数都大于右子树节点的父节点就是满足情况的。所以这也是为什么我想的单调递减再递增的想法是错误的。

解决办法
根据二叉搜索树的性质,当遍历到右子树,右子树上所有节点的值都大于右子树的父节点的值。所以当找到第一个大于当前值的元素的时候,就说明到了右子树,就需要找到这个右子树的父节点是哪个,然后遍历后面的元素让它们都满足大于这个父节点的值。
由于前序遍历上面的根节点先遍历,要去找一个节点的父节点,就需要在递减序列中找到第一个大于当前节点的值,所以使用栈来将递减时的值存储起来。在开始的时候递减序列会一直被存入栈中,因为
**!stack.isEmpty() && preorder[i] > stack.peek()**中的后一个条件一直不满足。当出现第一个大于栈顶的值的时候,条件满足,就把所有堆栈中小于当前节点的值都抛出去,意味着现在栈顶是第一个大于当前元素的值,也就是当前元素的父节点。而后继续遍历,i1就等于父节点的值,当后面的值出现小于父节点的值,就违背了搜索二叉树的性质,return false;否则就继续遍历把递减序列又放进堆栈,找到第一个递增的拐点,以此类推。
如果都遍历完就返回true
自己又重新写了一遍

class Solution {
    public boolean verifyPreorder(int[] preorder) {
        Stack<Integer> stack = new Stack<>();
        Integer i1 = Integer.MAX_VALUE;
        int flag = 0;
        for (int i = 0; i < preorder.length; i++) {
            if (preorder[i] < i1 && flag == 1) {
                return false;
            }
            if (preorder[i] < i1 && flag == 0) {
                stack.push(preorder[i]);
                i1 = preorder[i];
                continue;
            }
            while (!stack.empty() && preorder[i] > stack.peek()) {
                i1 = stack.pop();
                flag = 1;
            }
            stack.push(preorder[i]);
        }
        return true;
    }
}

遍历,递减序列,入栈,continue(flag表示是否首次);
出现拐点,出栈,找到父节点,赋值给i1,当前节点入栈;
遍历后面的,出现小于i1的就returnfalse,否则看是否仍然是拐点,重复步骤;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值