输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:
示例 1:
输入: [1,6,3,2,5]
输出: false
示例 2:
输入: [1,3,2,6,5]
输出: true
提示:
数组长度 <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof
思路:
我们都知道,二叉树的后序遍历,先访问左子树,然后是右子树,最后是自身这个节点。所以根节点必定是在序列的最后。
基于这个特点,我们的解题思路:
1、获取根节点root,对应的下标是high
2、在root这个数之前找到第一个大于等于root的数,并标记它的下标为index,从而将数组分成两个子数组,[0,index - 1],[index,high - 1],其中理论上[0,index - 1]是root的左子树,[index,high - 1]是root的右子树
3、由二叉搜索树的定义,我们需要判断[index,high - 1]是否都是大于等于root的数,如果其中含有一个数小于root,说明这个序列不是二叉搜索树的后序遍历序列,返回false,否则,如果符合了,那么就进入递归,判断这两个子树是否符合。
对应的代码:
class Solution {
public boolean verifyPostorder(int[] postorder) {
return judge(postorder,0,postorder.length - 1);
}
public boolean judge(int[] postOrder,int low,int high){
if(low < high){
int root = postOrder[high];//获取根节点的值
//遍历数组,从而找到第一个大于等于根节点的数,从而将子数组分成两个子数组
int index = findElement(postOrder,low,high - 1,root);
if(index != -1) {
/*
index等于-1,说明都是小于根节点的值,那么只需要对这一部分进
行判断即可,即判断这一个子树即可,否则需要划分成两个子数组,
分别对两个子数组进行相应的判断,如果两个子数组符合要求,那
么在进行相应的递归否则直接返回false。
但是由于在上面调用findElement方法找到第一个大于root的值,
那么就已经判断了左子树[low,index - 1]是明显都是小于root的
数,即符合左子树的节点的数都是小于root的数,所以只需要判断
右子树即可
*/
boolean flag = isRight(postOrder,index,high - 1,root);
return flag && judge(postOrder,low,index - 1) && judge(postOrder,index,high - 1);
}
return judge(postOrder,low,high - 1); //在数组都是小于根节点的时候,判断它的左子树是否符合二叉搜索树要求
}else{
//如果没有节点了,那么直接返回true
return true;
}
}
//判断当前数组是否是root的右子树
public boolean isRight(int[] postOrder,int low,int high,int root){
while(low <= high){
if(postOrder[low] < root)
return false;
low++;
}
return true;
}
public int findElement(int[] postOrder,int low,int high,int root){
while(low <= high){
if(postOrder[low] >= root)
return low;
low++;
}
return -1;//返回-1的时候,说明都是小于root的数
}
}
运行结果: