255. Verify Preorder Sequence in Binary Search Tree

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.

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

Ideas:

1. Divide and conquer, it needs Nlg(N) time.

2. linear solution

Kinda simulate the traversal, keeping a stack of nodes (just their values) of which we‘re still in the left subtree. If the next number is smaller than the last stack value, then we‘re still in the left subtree of all stack nodes, so just push the new one onto the stack. But before that, pop all smaller ancestor values, as we must now be in their right subtrees (or even further, in the right subtree of an ancestor). Also, use the popped values as a lower bound, since being in their right subtree means we must never come across a smaller number anymore.

Solutions:

Linear solution with clean code:

 1 bool verifyPreorder(int[] preorder) {
 2     int low = MIN_INT;
 3     stack<int> path;
 4     for (int p : preorder) {
 5         if (p < low)
 6             return false;
 7         while (!path.empty() && p > path.top()){
 8             low = path.top();
 9             path.pop()
10         }
11         path.push(p);
12     }
13     return true;
14 }    

If you really can not understand the code, see this post:

The idea is traversing the preorder list and using a stack to store all predecessors. curr_p is a predecessor of current node and current node is in the right subtree of curr_p.

For example, for the following bst with preorder 6,3,1,2,5,4,7:

              6
            /  \  
           3    7
          /           1   5
         \   /
         2  4   

We push to stack before we see 2. So at 2 the stack is 6,3,1. For 2, we pop stack until we see 3 which is greater than 2 and curr_p is 1. 2 is in left subtree of 3 and is right child of 1. Stack is 6,3,2 now. Then we see 5, and we pop stack until 6 and curr_p is 3. Stack now is 6,5. Then we see 4 and push to stack. At 7, we pop stack until empty and curr_p is 6.

 1 bool verifyPreorder(vector<int>& preorder){
 2     // using stack
 3     int sz = preorder.size();
 4     if(sz < 2) return true;
 5     stack<int> s;
 6     s.push(preorder[0]);
 7     int curr_p = INT_MIN;
 8     for(int i=1; i<sz; i++){ 
 9         if(s.empty() || preorder[i]<s.top()){ // if current node is less than stack top, then go to left subtree
10             if(preorder[i]<curr_p) return false; 
11             s.push(preorder[i]);
12         }
13         else{
14             while(!s.empty() && s.top()<preorder[i]){ //find curr_p such that current node is right child of curr_p
15                 curr_p = s.top();
16                 s.pop();
17             }
18             s.push(preorder[i]);
19         }
20     }
21     return true;
22 }

 

I also combine the following 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.

Finally, a divide and conquer solution:

Recursively examine every key in the array. For each BST node, its key must be greater than all keys in left subtree and less than keys in right subtree.

Since given preorder sequence, the first element is always the root. Partition the array by the key of root, find the index of the first number greater than it.

Base case:

  1. start index exceeds end index, the array to be checked is empty, return true;
  2. root key is not within upper and lower boundaries, return false.

Solution:

public boolean verifyPreorder(int[] preorder) {
    return verify(preorder, 0, preorder.length - 1, Integer.MIN_VALUE, Integer.MAX_VALUE);
}

private boolean verify(int[] preorder, int start, int end, int min, int max) {
    if (start > end) {
        return true;
    }
    int root = preorder[start];
    if (root > max || root < min) {
        return false;
    }
    
    int rightIndex = start;
    while (rightIndex <= end && preorder[rightIndex] <= root) {
        rightIndex++;
    }
    return verify(preorder, start + 1, rightIndex - 1, min, root) && verify(preorder, rightIndex, end, root, max);
}

 

以上是关于255. Verify Preorder Sequence in Binary Search Tree的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode 255. Verify Preorder Sequence in Binary Search Tree

[LeetCode] 255. Verify Preorder Sequence in Binary Search Tree

[LeetCode] 255. Verify Preorder Sequence in Binary Search Tree 楠岃瘉浜屽弶鎼滅储鏍戠殑鍏堝簭搴忓垪

LeetCode Verify Preorder Sequence in Binary Search Tree

Verify Preorder Serialization of a Binary Tree

LeetCode Verify Preorder Serialization of a Binary Tree