255. Verify Preorder Sequence in Binary Search Tree

本文探讨了如何验证一个整数序列是否为二叉搜索树的正确前序遍历序列,提供了三种方法:栈法、递归法及O(1)空间复杂度的解决方案,深入解析了每种方法的思路与实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

255. Verify Preorder Sequence in Binary Search Tree


Given an array of numbers, verify whether it is the correct preorder traversal sequence of a binary search tree.

You may assume each number in the sequence is unique.

Consider the following binary search tree:

 5
/ \

2 6
/
1 3
Example 1:

Input: [5,2,6,1,3]
Output: false

Example 2:

Input: [5,2,1,3,6]
Output: true

Follow up:

Could you do it using only constant space complexity?

grandyang:http://www.cnblogs.com/grandyang/p/5327635.html

方法1: stack

思路:

这道题的重点检查BST的性质是否满足:在遍历数组的过程中,递减的话,说明这个数组还在向左孩子遍历,没有办法invalidate。什么时候可以停止了?当遇到一个元素比当前栈顶要大,说明右孩子出现了,我们需要知道它是谁的右孩子。开始弹栈寻找这个右孩子的父节点,也就是最后一个比它大的节点。找到这个点p之后,说明p的左节点已经遍历结束了,任何后续数字,不能小于这个数。这个lower bound在遇到新的右孩子时被不断更新,如果遍历结束都没有发现打破这个条件的数字,可以return true。

discussion: https://leetcode.com/problems/verify-preorder-sequence-in-binary-search-tree/discuss/68185/C%2B%2B-easy-to-understand-solution-with-thought-process-and-detailed-explanation

THOUGHT: We first look at the property of preorder traversal: we print left child’s value of current node all the way until we reached a leaf node (you will see numbers decreasing), then we start printing the value of a node (let it be rc) which is the right child of one of the nodes (let it be node p) we already traversed. When do you know it’s a right child node’s value? It’s when you see a value greater than the last one. Also,till here we know, all the nodes in p’s left subtree have been read in the serialized array, and this property is maintained:

left subtree ‘s value < p ’s value < rc’s value
Since all the nodes whose value is smaller than p are already read, all the nodes’ value to be read after should have greater value than p’s value, so p’s value becomes the lower bound for any upcoming node.

p ’s value < upcoming value in array
Otherwise, it’s not valid. So the key here is to find the lower bound for upcoming nodes, which equals to find p.

To translate this into code: looking for the trend of numbers, if it’s decreasing, it’s still traversing the left child node all the way down, we push the value into stack. When we read a value greater than the last one, we know the current value belongs to a right node (let it be rc: right child) of one of the previous nodes (let it be p) we pushed to stack, in other words, p is a parent node of the current node rc. Due to the property of preorder traversal, p’s value is pushed to stack before its left subtree nodes, so to find the parent node, we pop all the nodes in its left subtree, and the last popped node whose value is smaller than rc is rc’s parent p, whose value becomes the lower bound. Then we keep reading the serialized array, in any case we see any value not greater than the lower bound, we return false. Lower bound is updated whenever we read a right child node’s value.

class Solution {
public:
    bool verifyPreorder(vector<int>& preorder) {
        if (preorder.empty()) return true;
        stack<int> st;
        int mn = INT_MIN;
        for (int a: preorder) {
            if (a < mn) return false;
            while (!st.empty() && a > st.top()) {
                mn = st.top();
                st.pop();
            }
            st.push(a);
        }
        return true;
    }
};

方法2: recursion

思路:

class Solution {
public:
    bool verifyPreorder(vector<int>& preorder) {
        if (preorder.empty()) return true;
        int mn = INT_MIN, mx = INT_MAX;
        return vHelper(preorder, 0, preorder.size() - 1, mn, mx);
    }
    
    bool vHelper(vector<int> & preorder, int start, int end, int mn, int mx) {
        if (start > end || start >= preorder.size()) return true;
        int i = start + 1;
        while (i < preorder.size() && preorder[i] < preorder[start]) i++;
        return preorder[start] > mn 
            && preorder[start] < mx 
            && vHelper(preorder, start + 1, i - 1, mn, preorder[start]) 
            && vHelper(preorder, i, end, preorder[start], mx);
    }
};

方法3: O(1) space

思路:

follow up里面限制只能使用O(1) space,那么就不能用stack来存前节点,那么就原位修改preorder。

class Solution {
public:
    bool verifyPreorder(vector<int>& preorder) {
        int low = INT_MIN, i = -1;
        for (auto a : preorder) {
            if (a < low) return false;
            while (i >= 0 && a > preorder[i]) {
                low = preorder[i--];
            }
            preorder[++i] = a;
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值