二叉搜索树的遍历序列
个人博客
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回
true
,否则返回false
。假设输入的数组的任意两个数字都互不相同。
题解
-
递归分治
- 算法思想
- 递归的判断搜索树的左右子树是不是符合左子树都小于根节点,右子树都大于根节点
- 如何设置递归终止条件
- 当查找到左子树有元素大于根节点时或者右子树有元素小于根节点时返回 false
- 当数组大小小于等于 2 的时候
- 复杂度分析
- 时间复杂度 O(N^2): 每次调用 recur(i,j)recur(i,j) 减去一个根节点,因此递归占用 O(N)O(N) ;最差情况下(即当树退化为链表),每轮递归都需遍历树所有节点,占用O(n)。
- 空间复杂度O(n):最差情况下(树退化为链表),递归深度将达 n
class Solution { public boolean verifyPostorder(int[] postorder) { return virifyBinarySearchRecurse(postorder,0,postorder.length-1); } boolean virifyBinarySearchRecurse(int[] nodes,int start,int end){ if(end - start <= 1)return true; int rightstart = end -1; boolean finded = false; for(int i = start;i < end;i++){ if(nodes[i] > nodes[end] && !finded){ rightstart = i - 1; finded = true; } if(nodes[i] < nodes[end] && finded)return false; } return virifyBinarySearchRecurse(nodes,start,rightstart) && virifyBinarySearchRecurse(nodes,rightstart + 1,end-1); } }
- 算法思想
-
单调栈
-
算法思想
- 后续遍历的倒序为
[ 根节点 | 右子树 | 左子树 ]
,此时可以利用单调栈,当将要加入的节点的值大于栈顶时,直接加入,当要加入的元素小于栈顶的时候,将栈顶元素弹出,判断此时栈顶元素是否大于将要加入的元素,直到栈顶元素小于将要加入元素或者栈空。然后将要加入的元素加入 - 在此过程中,如果将要加入的元素大于最后一次弹出的元素,则说明不是二叉搜索树
- 后续遍历的倒序为
-
复杂度分析
- 时间复杂度 O(n):每个元素出栈入栈一次,
- 空间复杂度 O(n):二叉树搜索树退化为单链表,栈的深度为 n
class Solution { public boolean verifyPostorder(int[] postorder) { Deque<Integer> stack = new ArrayDeque<>(); int prev = Integer.MAX_VALUE; for(int i = postorder.length -1;i >= 0;i--){ if(postorder[i] > prev)return false; while(!stack.isEmpty() && postorder[i] < stack.peek()){ prev = stack.pop(); } stack.push(postorder[i]); } return true; } }
-
总结
- 利用单调栈方法时间复杂度显然更好,但是思路确实挺难,我想了好久才明白,让我去证明正确性,估计是不可能的了。