Q:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
T:
1.使用递归解决,根节点左子树上所有节点比根节点小,根节点右子树上所有节点比根节点大。
bool VerifySquenceOfBST(vector<int> sequence){
if (sequence.empty())
return false;
return VerifySquence(sequence);
}
static bool VerifySquence(vector<int> sequence) {
vector<int> pre;
vector<int> pro;
if (sequence.empty())
return true;
int size = sequence.size();
int root = sequence[size - 1];
int i = 0;
for (i = 0; i < sequence.size() - 1; i++) {
pre.push_back(sequence[i]);
if (sequence[i] > root)
break;
}
for (i += 1; i < sequence.size() - 1; i++) {
pro.push_back(sequence[i]);
if (sequence[i] < root)
return false;
}
return VerifySquence(pre) && VerifySquence(pro);
}
P.S.我开始想用一个函数解决递归,结果遇到一个悖论:“如果本身序列为空返回false,但子树为空返回true”,so我只能用两个函数解决了。后来在评论区看了可以不用两个函数的方法,我也修正了一下自己的代码:
bool VerifySquenceOfBST(vector<int> sequence){
vector<int> pre;
vector<int> pro;
if (sequence.empty())
return false;
int size = sequence.size();
int root = sequence[size - 1];
int i = 0;
for (i = 0; i < sequence.size() - 1; i++) {
pre.push_back(sequence[i]);
if (sequence[i] > root)
break;
}
for (i += 1; i < sequence.size() - 1; i++) {
pro.push_back(sequence[i]);
if (sequence[i] < root)
return false;
}
bool left = true;
bool right = true;
if(!pre.empty())
left = VerifySquenceOfBST(pre);
if(!pro.empty())
right = VerifySquenceOfBST(pro);
return left && right;
}
2.非递归
bool VerifySquenceOfBST(vector<int> sequence) {
if (sequence.empty())
return false;
int size = sequence.size();
int i = 0;
while (--size) {
while (sequence[i++] < sequence[size]);
while (sequence[i++] > sequence[size]);
if (i < size)
return false;
i = 0;
}
return true;
}
3.讨论区看到一种神仙解法:@lyick
一个非常规方法,看了半天没看到一样的,提供一个新思路。
前面有道题是“栈的压入、弹出序列”。
写这道题的例子时发现二叉树的中序序列和后序序列就满足栈的压入弹出序列关系。
即如果把中序序列当做栈的压入序列,那么后序序列是该栈的一个弹出序列。
而BST的中序是排序数组。因此将本题的序列排序作为中序序列,引用前面题的答案判断两序列是否满足上述关系即可。
我思考了半天,只能这么说通,一个中序和一个后序可以唯一对应一棵树。如果满足中序和后序,可以确定是一棵树,而这棵树的中序是单调递增,以此判断是二叉搜索树。
引用:栈的压入、弹出系列
bool VerifySquenceOfBST(vector<int> sequence) {
if(sequence.empty())
return false;
vector<int> sequence2 = sequence;
sort(sequence2.begin(), sequence2.end());
stack<int> s;
int out = 0;
for (int i = 0; i < sequence2.size(); i++) {
s.push(sequence2[i]);
while (!s.empty() && s.top() == sequence[out]) {
s.pop();
out++;
}
}
return s.empty();
}