Given An array of numbers, verify whether it is the correct preorder traversal sequence of a binary search tree.
Assume each of the sequence is unique.
Follow up:
Could does 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, and then we ' re still in the left subtree of all stacks nodes, so just Push the new one onto the stack. But before this, pop all smaller ancestor values, as we must now is 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 on their right subtree means we must never come across a smaller Number anymore.
Solutions:
Linear Solution with Clean code:
1 BOOLVerifypreorder (int[] preorder) {2 intLow =Min_int;3stack<int>path;4 for(intP:preorder) {5 if(P <Low )6 return false;7 while(!path.empty () && p >Path.top ()) {8Low =path.top ();9 Path.pop ()Ten } One Path.push (p); A } - return true; -}
If you really can isn't understand the code, see this post:
The idea was traversing the preorder list and using a stack to store all predecessors. Curr_p is a predecessor of current node and current node are in the right subtree of curr_p.
For example, the following BST with preorder 6,3,1,2,5,4,7:
6 / \ 3 7 / 1 5 \ / 2 4
We push to the stack before we see 2. So at 2, the stack is 6,3,1. For 2, we pops stack until we see 3 which are greater than 2 and curr_p is 1. 2 are in left subtree of 3 and are right-child of 1. Stack is 6,3,2 now. Then we see 5, and we pop stack until 6 and curr_p are 3. Stack now is 6,5. Then we see 4 and push to stack. At 7, we pops stack until empty and curr_p is 6.
1 BOOLVerifypreorder (vector<int>&preorder) {2 //using Stack3 intSZ =preorder.size ();4 if(SZ <2)return true;5stack<int>s;6S.push (preorder[0]);7 intCurr_p =int_min;8 for(intI=1; i<sz; i++){ 9 if(S.empty () | | preorder[i]<s.top ()) {//If current node was less than stack top and then go to left subtreeTen if(preorder[i]<curr_p)return false; One S.push (Preorder[i]); A } - Else{ - while(!s.empty () && s.top () <preorder[i]) {//find curr_p Such that the current node was right child of curr_p theCurr_p =s.top (); - S.pop (); - } - S.push (Preorder[i]); + } - } + return true; A}
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 The until we reached a leaf node (you'll see numbers decreasing) and 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 does 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 with P ' s left subtree has been read in the serialized array, and this property is Mai Ntained:
value < p ’s value < rc’s value
Since all the nodes whose value is smaller than P was already read, all the nodes ' value to being read after should has Grea ter value than P ' s value, so P's value becomes the lower bound for any upcoming node.
value < upcoming value in array
Otherwise, it ' s not valid. so the keys here are to find the lower bound for upcoming nodes, and which equals to find p.
To translate the-code:looking for the trend of numbers, if it ' s decreasing, it's still traversing the left child no De all the the-the-the-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 chi LD) of one of the previous nodes (let it being 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 was pushed to stack before it left subtree nodes, so to find the Pare NT node, we pop all the nodes in it left subtree, and the last popped node whose value are smaller than RC is RC s parent P, whose value becomes the lower bound. Then we keep reading the serialized array, with 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, the its key must is greater than all keys in the left subtree and less than the 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:
- Start index exceeds end index, the array to being checked is empty, return true;
- Root key is not within upper and lower boundaries, return false.
Solution:
Public BooleanVerifypreorder (int[] preorder) { returnVerify (preorder, 0, preorder.length-1, Integer.min_value, Integer.max_value);}Private BooleanVerifyint[] Preorder,intStartintEndintMinintmax) { if(Start >end) { return true; } intRoot =Preorder[start]; if(Root > Max | | root <min) { return false; } intRightindex =start; while(Rightindex <= end && Preorder[rightindex] <=root) {Rightindex++; } returnVerify (preorder, start + 1, rightIndex-1, Min, root) &&Verify (preorder, Rightindex, end, Root, max);}
255. Verify Preorder Sequence in Binary Search Tree