博文中会简要介绍Leetcode P0255题目分析及解题思路。
“Verify Preorder Sequence in Binary Search Tree”是一道中等难度的题目,这道题有两种思路,第一种思路是利用前序遍历和二叉搜索树的特性,用栈来记录前序遍历到每个结点时该结点在栈中的位置,也即结点在之后遍历中出现的顺序;第二种思路则是用中序遍历和前序遍历构造二叉搜索树的方法,模拟一遍二叉搜索树的构造过程,如果模拟不成功则说明前序遍历是有问题的。
Given an array of unique integers
preorder
, returntrue
if it is the correct preorder traversal sequence of a binary search tree.
先简单讲解第一种思路。我们模拟二叉搜索树的前序遍历,利用栈来保存结点,如果下一个结点的值小于栈顶结点的值,则我们仍位于所有栈内结点的左侧子树中,因此只需将新的结点值入栈即可;反之,弹出所有较小的祖先值直到栈顶的结点值大于当前结点值,此时我们将位于上一个弹出的栈顶结点的右侧子树中,也是应当存在当前结点的子树。另外,将最后一个弹出的值作为下限,因为位于其正确的子树中意味着我们不应当再遇到更小的值。
以下是Java的题解代码实现。
class Solution {
public boolean verifyPreorder(int[] preorder) {
int low = Integer.MIN_VALUE;
Deque<Integer> path = new LinkedList<>();
for (int p: preorder) {
if (p < low)
return false;
while (!path.isEmpty() && p > path.peekFirst()) {
low = path.pollFirst();
}
path.offerFirst(p);
}
return true;
}
}
第二种思路比较直接。首先对给定的前序遍历结果排序,由于是二叉搜索树,所以从小到大排序后得到的就是某个二叉搜索树的中序遍历结果。然后利用前序遍历和中序遍历模拟一遍树的构造过程,如果发现不能构造则说明给定的前序遍历结果存在问题。
以下是第二种思路的Java题解代码实现。
class Solution {
public boolean verifyPreorder(int[] preorder) {
int N = preorder.length;
// Obtain the inorder of the potential binary search tree
int[] inorder = Arrays.copyOf(preorder, N);
Arrays.sort(inorder);
this.preorder = preorder;
this.inorder = inorder;
return this.dfs(0, 0, N-1);
}
private int[] preorder, inorder;
private boolean dfs(int itr, int beg, int end) {
if (beg > end)
return true;
int mid = -1;
for (int idx=beg; idx<=end; ++idx) {
if (this.preorder[itr] == this.inorder[idx]) {
mid = idx;
}
}
// Cannot find the root located in the right position
if (mid == -1)
return false;
return (this.dfs(itr+1, beg, mid-1) && this.dfs(itr+mid-beg+1, mid+1, end));
}
}
以下是C++的题解代码实现。
class Solution {
public:
bool verifyPreorder(vector<int>& preorder) {
int low = INT_MIN;
stack<int> path;
for (int p: preorder) {
if (p < low)
return false;
while (!path.empty() && p > path.top()) {
low = path.top();
path.pop();
}
path.push(p);
}
return true;
}
};