判断数组是否是二叉搜索树的后序遍历序列
2015-07-17
次访问
剑指offer面试题系列
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是返回true,否则返回false。假设输入的数组的任意两个数字都不相同。
分析
拿到本题时,其实很快就想出了思路,就是在实现的过程中有几个细节问题没有注意到,导致调试了半天。这个在后面的备注里会提到。先说思路:
由于是后序遍历二叉树产生的序列,因为后序遍历的特点是最后遍历根节点,所以自然数组的最后一个元素就是根节点了。又因为是二叉排序树,所以根节点的左子树的全部元素是小于根节点的,相应的右子树全部大于根节点。根据这个性质,可以很容易在数组中划分出来哪部分是左子树,哪部分是右子树。只要从数组的第一个元素开始遍历,直到遍历到大于这个根节点的元素为止,前面的是左子树,后面的自然就是右子树了。
依次类推,使用递归可以实现之。
代码
package com.tree;
/*判断输入数组是否是二叉搜索树的后序遍历序列
* */
public class BinaryTreeEx {
private static int[] arr1 = { 1, 2, 4, 3, 7, 9, 6, 8 };
private static int[] arr2 = { 1, 3, 2 };
private static int[] arr3 = { 3, 2, 5, 6, 4 };
private static int[] arr = { 3, 2, 4, 1 };
public static boolean isPostOrderSeq(int[] arr, int start, int end) {
boolean flag = true;
if (start >= end) { //先判断输入是否合适
return flag;
}
int root = arr[end];
int i = start; //i从start开始遍历
int pos = 0;
while (i < arr.length && arr[i] < root)
i++;
pos = i;
int right_len = end - pos;//左子树长度
int left_len = pos - start;//右子树长度
if (left_len > 0) {
for (int k = start; k < left_len; k++) {
if (arr[k] > root) {
flag = false;
break;
}
}
}
if (flag && right_len > 0) {
for (int k = pos; k < end; k++) {
if (arr[k] < root) {
flag = false;
break;
}
}
}
if (flag)
flag = isPostOrderSeq(arr, start, pos - 1);
if (flag)
flag = isPostOrderSeq(arr, pos, end - 1);
return flag;
}
public static void main(String[] args) {
if (isPostOrderSeq(arr, 0, arr.length - 1))
System.out.println("该序列是后序遍历序列");
else
System.out.println("该序列不是后序遍历序列");
}
}
备注
有两个地方需要注意:
第一,是每次递归划分左右子树的变量 i 的起点,因为每次将 i=0,在调试时费了不少功夫;而计算左右子树的表达式也要注意;
第二,在递归右子树时,记得输入参数的时候将 end 变量减去 1,因为每次都把最后一个结点踢出来了。
总结
前面很多题是思路没有想清楚,实现没啥问题;这个题是思路没有想清楚,实现的细节上费了很大功夫。以后做题,思路先要想清楚,然后在细节上,特别是一些变量的设置上要注意。