Given a list of numbers, determine whether it can represent the pre-order traversal list of a binary search tree (BST).
Input
The first line contains the number of test cases, T. T lines follow, consisting of two lines each.
The first line of each test case contains the number of nodes in the tree, N. In next line there will a list of N unique numbers, where each number is from the range [1, N].
Output
For each test case, print the string “YES” if there exists a BST whose pre-order traversal is equal to the list, otherwise print the string “NO” (without quotes, preserving capitalization).
Constraints
1 ≤ T ≤ 10
1 ≤ N ≤ 100
Sample Input
5
3
1 2 3
3
2 1 3
6
3 2 1 5 4 6
4
1 3 4 2
5
3 4 5 1 2
Sample Output
YES
YES
YES
NO
NO
Explanation
- The first three cases are from the above examples.
- In case 4, after encountering the 3, the 4tells us we are on the right sub-tree, which means no values smaller than 3 are allowed any longer. So when we see the 2 we know the list is invalid.
- Similarly, in case 5, after encountering the 3, the 4 and 5 tell us we are on the right sub-tree, so the subsequent encounter of values 2 and 1, which belong in the left sub-tree, tells us that the list is not valid as a pre-order traversal of a BST.
public static boolean isValidPreorderBST(int[] A) { return isValidPreorderBST(A, 0, A.length-1); } public static boolean isValidPreorderBST(int[] A, int start, int end) { if(start >= end) return true; int i=start+1; for(; i<=end; i++) { if(A[i] > A[start]) break; } int j = i; while(j <= end) { if(A[j++] <= A[start]) return false; } return isValidPreorderBST(A, start+1, i-1) && isValidPreorderBST(A, i, end); } public static void main(String[] args) { String[] cases = new String[]{"1 2 3", "2 1 3", "3 2 1 5 4 6", "1 3 4 2", "3 4 5 1 2"}; for(String s:cases) { String[] nums = s.split("\\s"); int[] A = new int[nums.length]; for(int i=0; i<A.length; i++) { A[i] = Integer.parseInt(nums[i]); } System.out.println(isValidPreorderBST(A)); } }
重构了一下,添加了min数组,保存从当前位置往后的最小值,省去了继续搜索比根节点值小的元素的时间。
public static boolean isValidPreorderBST(int[] A) { int n = A.length; if(n <= 1) return true; int[] min = new int[n]; min[n-1] = A[n-1]; for(int i=n-2; i>=0; i--) { min[i] = Math.min(min[i+1], A[i]); } return isValidPreorderBST(A, min, 0, n-1); } private static boolean isValidPreorderBST(int[] A, int[] min, int start, int end) { if(start >= end) return true; int i=start+1; for(; i<=end; i++) { if(A[i] > A[start]) break; } if(i<end && min[i+1] <= A[start]) return false; return isValidPreorderBST(A, min, start+1, i-1) && isValidPreorderBST(A, min, i, end); }
以上解法的时间复杂度都是O(N^2)。
以下链接提供了O(N)的解法。
http://www.geeksforgeeks.org/construct-bst-from-given-preorder-traversa/