力扣对应题目链接:LCR 152. 验证二叉搜索树的后序遍历序列 - 力扣(LeetCode)
牛客对应题目链接:二叉搜索树的后序遍历序列_牛客题霸_牛客网 (nowcoder.com)
核心考点 : BST 特征的理解。
一、《剑指Offer》对应内容
二、分析题目
看清题意,是二叉搜索树后序遍历。
二叉搜索树:它或者是一棵空树,或者是具有下列性质的二叉树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值。
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。
后序遍历:先左后右再根。
BST 的后序序列的合法序列是,对于一个序列 S,最后一个元素是 x (也就是 root 节点),如果去掉最后一个元素的序列为 T,那么 T 满足:T 可以分成两段,前一段(左子树)小于 x,后一段(右子树)大于 x,且这两段(子树)都是合法的后序序列。
验证思路:当前序列,及其子序列必须都满足上述定义。
三、代码
//牛客
class Solution {
public:
bool f(vector<int>& sequence, int st, int ed)
{
if (st >= ed) return true;
int root = sequence[ed];
// 先遍历左半部分,也就是整体都要比root小,拿到左子树序列
int i = st;
while (i < ed && sequence[i] < root)
i++;
// 再检测右子树是否符合大于root的条件,要从i开始,也就是右半部分的开始
for (int j = i; j < ed; j++)
if (sequence[j] < root) //在合法位置处,当前值小于root,不满足BST定义
return false;
// 还要在检测left和right各自是否也满足
return f(sequence, st, i - 1) && f(sequence, i, ed - 1);
}
bool VerifySquenceOfBST(vector<int> sequence) {
int n = sequence.size();
if (n <= 0) return false;
return f(sequence, 0, n - 1);
}
};
//力扣
class Solution {
public:
bool f(vector<int>& postorder, int st, int ed)
{
if(st>=ed) return true;
int root=postorder[ed];
int i=st;
while(i<ed && postorder[i]<root)
i++;
for(int j=i; j<ed; j++)
if(postorder[j]<root)
return false;
return f(postorder, st, i-1) && f(postorder, i, ed-1);
}
bool verifyTreeOrder(vector<int>& postorder) {
int n=postorder.size();
return f(postorder, 0, n-1);
}
};
四、相关题目
输入一个整数数组,判断该数组是不是某二叉搜索树的前序遍历的结果。
这和前面问题的后序遍历很类似,只是在前序遍历得到的序列中,第一个数字是根节点的值。
五、举一反三
105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)
如果是要求处理一颗二叉树的遍历序列,我们可以先找到二叉树的根节点,再基于根结点把整棵树的遍历序列拆分成左子树对应的子序列和右子树对应的子序列,接下来再递归地处理这两个子序列。
//力扣
//从前序与中序遍历序列构造二叉树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* traversal(vector<int>& preorder, int pre_st, int pre_ed, vector<int>& inorder, int in_st, int in_ed)
{
if(pre_st>pre_ed || in_st>in_ed) return nullptr;
TreeNode* root=new TreeNode(preorder[pre_st]);
for(int i=0; i<inorder.size(); i++)
{
if(inorder[i]==preorder[pre_st])
{
root->left=traversal(preorder, pre_st+1, (pre_st+1)+(i-in_st)-1, inorder, in_st, i-1);
root->right=traversal(preorder, (pre_st+1)+(i-in_st)-1+1, pre_ed, inorder, i+1, in_ed);
break;
}
}
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n=preorder.size(), m=inorder.size();
return traversal(preorder, 0, n-1, inorder, 0, m-1);
}
};
//力扣
//从中序与后序遍历序列构造二叉树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* traversal(vector<int>& inorder, int in_st, int in_ed, vector<int>& postorder, int post_st, int post_ed)
{
if(in_st>in_ed || post_st>post_ed) return nullptr;
TreeNode* root=new TreeNode(postorder[post_ed]);
for(int i=0; i<inorder.size(); i++)
{
if(inorder[i]==postorder[post_ed])
{
root->left=traversal(inorder, in_st, i-1, postorder, post_st, post_st+(i-in_st)-1);
root->right=traversal(inorder, i+1, in_ed, postorder, post_st+(i-in_st), post_ed-1);
break;
}
}
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
int n=inorder.size(), m=postorder.size();
return traversal(inorder, 0, n-1, postorder, 0, m-1);
}
};