http://www.zrzahid.com/check-postordered-array-forms-a-bst/
http://louie.link/Algorithm-Practice/Algorithm%20Practice/24_VerifyPostOrderSquenceOfBST/
http://louie.link/Algorithm-Practice/Algorithm%20Practice/24_VerifyPostOrderSquenceOfBST/
https://github.com/xieqilu/Qilu-leetcode/blob/master/B206.ValidatePostorderTraversalBST.cs
验证二叉树后序遍历序列
Given an array that contains a Post order traversal of a Binary Tree. Check if a possible Binary Tree formed from the postorder traversal is a Binary Search Tree.
For example, a1=[1, 3, 4, 2, 7, 6, 5] is a BST but a2=[1, 3, 4, 6, 7, 2, 5] is not a BST.
5 5 / \ / \ 2 6 4 2 / \ \ / \ 1 4 7 3 7 / / / 3 1 6 (a1) (a2)
In order to be a BST, a binary tree should satisfy that any subtree rooted at node r is greater than all nodes in its left subtree and smaller than nodes in its right subtree. Now, in post order traversal we traverse left subtree first then the right subtree and at last the root. Thus, if the array is a post traversal of a BST, then a[0..n-1] can be divided into two parts a[0..i-1] and a[i, n-2], where
- Each item in left subtree a[0..i-1] is less than a[n-1]
- Each item in right subtree a[i..n-2] is greater than a[n-1]
- Both left subtree a[0..i-1] and right subtree a[i..n-2] are BSTs
So, for the given root a[n-1] we can find the start of a potential right subtree by scanning the array from left to right and check where the element is bigger than root. left side of this point is a left subtree. We also need to do sanity check whether the right subtree contains elements greater than root.
{1, 3, 4, 2, 7, 6, 5} 5 ^ / \ / \ 2 6 {1, 3, 4, 2} {7,6} / \ \ ^ ^ 1 4 7 / \ \ / {1} {3,4} {7} 3 ^ / {3}
Below is the implementation of this idea which runs in O(ngln) time in average case where the tree is a balanced binary tree and O(n) space. The worst case complexity however is O(n^2) in case of a tall binary tree such as a=[1,2,3,4,5]
5 / 4 / 3 / 2 / 1
public static boolean isBSTPostOrder(int[] a, int p, int q){ int n = q-p+1;; //base case always true for 1 element if(n < 2){ return true; } //partition into left subtree a[p..right-1] and right subtree a[right..q-1] int right = p; while(a[right] < a[q]) right++; //check validity of right subtree int i = right; while(i < q && a[i] > a[q]) i++; if(i < q){ return false; } return isBSTPostOrder(a, p, right-1) && isBSTPostOrder(a, right, q-1); }
public static boolean VerifySquenceOfBST(int[] sequence) { if (sequence == null || sequence.length == 0) return false; return helper(sequence, 0, sequence.length - 1); // [lo, hi] } private static boolean helper(int[] sequence, int lo, int hi) { if (lo >= hi) //since we used 'leftRoot + 1, hi - 1', lo could > hi return true; int root = sequence[hi]; int leftRoot = hi - 1; //left to root // first, find left-subtree's root, traverse backwards while (leftRoot >= lo) { if (sequence[leftRoot] < root) break; leftRoot--; } // we found the left-subtree's root, all the elements in left-subtree should be smaller than root value // keep traversing backward, if there exists an element > root, then invalid left subtree for (int i = leftRoot; i >= lo; i--) { if (sequence[i] > root) return false; } //hi - 1 is rightRoot return helper(sequence, lo, leftRoot) && helper(sequence, leftRoot + 1, hi - 1); }
https://github.com/xieqilu/Qilu-leetcode/blob/master/B206.ValidatePostorderTraversalBST.cs
Q:如何验证后序序列?
A:后序序列的顺序是
A:后序序列的顺序是
left - right - root
,而先序的顺序是root - left - right
。我们同样可以用本题的方法解,不过是从数组的后面向前面遍历,因为root在后面了。而且因为从后往前看是先遇到right再遇到left,所以我们要记录的是限定的最大值,而不再是最小值,栈pop的条件也变成pop所有比当前数大得数。栈的增长方向也是从高向低了。 public boolean IsValidPostOrderBst(int[] nums)
{
int i = nums.length;
int max = Integer.MAX_VALUE;
for (int j = nums.length - 1; j >= 0; j--)
{
if (nums[j] > max) return false;
while (i <= nums.length - 1 && nums[j] > nums[i])
max = nums[i++];
nums[--i] = nums[j];
}
return true;
}