[LeetCode] 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.

Follow up:
Could you do it using only constant space complexity?

这道题让给了我们一个一维数组,让我们验证其是否为一个二叉搜索树的先序遍历出的顺序,我们都知道二叉搜索树的性质是左<根<右,如果用中序遍历得到的结果就是有序数组,而先序遍历的结果就不是有序数组了,但是难道一点规律都没有了吗,其实规律还是有的,根据二叉搜索树的性质,当前节点的值一定大于其左子树中任何一个节点值,而且其右子树中的任何一个节点值都不能小于当前节点值,那么我们可以用这个性质来验证,举个例子,比如下面这棵二叉搜索树:

5
/ \
2   6
/ \
1   3

其先序遍历的结果是{5, 2, 1, 3, 6}, 我们先设一个最小值low,然后遍历数组,如果当前值小于这个最小值low,返回false,对于根节点,我们将其压入栈中,然后往后遍历,如果遇到的数字比栈顶元素小,说明是其左子树的点,继续压入栈中,直到遇到的数字比栈顶元素大,那么就是右边的值了,我们需要找到是哪个节点的右子树,所以我们更新low值并删掉栈顶元素,然后继续和下一个栈顶元素比较,如果还是大于,则继续更新low值和删掉栈顶,直到栈为空或者当前栈顶元素大于当前值停止,压入当前值,这样如果遍历完整个数组之前都没有返回false的话,最后返回true即可,参见代码如下:

解法一:

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

下面这种方法和上面的思路相同,为了使空间复杂度为常量,我们不能使用stack,所以我们直接修改preorder,将low值存在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;
    }
};

下面这种方法使用了分治法,跟之前那道验证二叉搜索树的题Validate Binary Search Tree的思路很类似,我们在递归函数中维护一个下界lower和上届upper,那么当前遍历到的节点值必须在(lower, upper)区间之内,然后我们在给定的区间内搜第一个大于当前节点值的点,然后以此为分界,左右两部分分别调用递归函数,注意左半部分的upper更新为当前节点值val,表明左子树的节点值都必须小于当前节点值,而右半部分的递归的lower更新为当前节点值val,表明右子树的节点值都必须大于当前节点值,如果左右两部分的返回结果均为真,则整体返回真,参见代码如下:

解法三:

class Solution {
public:
    bool verifyPreorder(vector<int>& preorder) {
        return helper(preorder, 0, preorder.size() - 1, INT_MIN, INT_MAX);
    }
    bool helper(vector<int> &preorder, int start, int end, int lower, int upper) {
        if (start > end) return true;
        int val = preorder[start], i = 0;
        if (val <= lower || val >= upper) return false;
        for (i = start + 1; i <= end; ++i) {
            if (preorder[i] >= val) break;
        }
        return helper(preorder, start + 1, i - 1, lower, val) && helper(preorder, i, end, val, upper);
    }
};

本文转自博客园Grandyang的博客,原文链接:验证二叉搜索树的先序序列[LeetCode] Verify Preorder Sequence in Binary Search Tree ,如需转载请自行联系原博主。

相关文章
|
4月前
【LeetCode 45】701.二叉搜索树中的插入操作
【LeetCode 45】701.二叉搜索树中的插入操作
25 1
|
4月前
【LeetCode 48】108.将有序数组转换为二叉搜索树
【LeetCode 48】108.将有序数组转换为二叉搜索树
57 0
|
4月前
【LeetCode 47】669.修剪二叉搜索树
【LeetCode 47】669.修剪二叉搜索树
17 0
|
4月前
【LeetCode 46】450.删除二叉搜索树的节点
【LeetCode 46】450.删除二叉搜索树的节点
35 0
|
5月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
6月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
76 6
|
6月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
145 2
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
99 1
|
5月前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
6月前
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
90 7