剑指23.二叉搜索树的后序遍历序列

题目描述

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。例如{5,76,9,11,10,8}返回true;而{7,4,6,5}返回false。
 

思路

二叉搜索树:树中没有值相同的两个节点,对于每一个节点,它左边所有节点都比它小,右边所有节点都比它大。

本题的关键在于找到后序遍历的规律。在后序遍历得到的序列中,最后一个数字是树的根节点的值。数组中前面的数字可以分为两部分:第一部分是左子树节点的值,它们都比根节点的值小;第二部分是右子树节点的值,它们都比根节点的值大。因此,是一个递归过程。

举一反三

        如果面试题要求处理一棵二叉树的遍历序列,则可以先找到二叉树的根节点,再基于根节点把整棵树的遍历序列拆分成左子树对应的子序列右子树对应的子序列,接下来再递归地处理这两个子序列。本题和剑指04“重建二叉树”都是这种思路。
 

解法1

import java.util.Arrays;
public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        if (sequence.length == 0) return false;
        int root = sequence[sequence.length - 1];
        // 二叉搜索树中左子树节点的值小于根节点的值
        int i = 0;   //  定义全局变量是为了记录分界点的索引
        for (;i < sequence.length - 1; i++){
            if (sequence[i] > root)
                break;
        }
        // 二叉搜索树中右子树节点的值大于根节点的值
        int j = i;
        for (; j < sequence.length - 1; j++){
            if (sequence[j] < root)
                return false;
        }
        // 判断左子树是不是二叉搜索树
        boolean left = true;
        if (i - 1 > 0)   // copyOfRange(oringinal,int from, int to),该方法是从original数组的下标from开始复制,到下标to结束
            left = VerifySquenceOfBST(Arrays.copyOfRange(sequence,0,i - 1));
        // 判断右子树是不是二叉搜索树
        boolean right = true;
        if (i < sequence.length - 2)
            right = VerifySquenceOfBST(Arrays.copyOfRange(sequence,i,sequence.length - 2));
        return left && right;
    }
}

 推荐解法2,解法1设计大量数组复制过程。。

☆☆解法2

public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        if (sequence.length == 0) return false;
        return helpVerify(sequence,0,sequence.length - 1);
    }
    private boolean helpVerify(int[] sequence,int start,int end){
        //递归到底的情况,很关键
        if (start >= end) return true; // start=end对应叶子节点;start>end对应右子树为空的情况
        int root = sequence[end];
        int i = start;
//        while (i < end && sequence[i] < root)
//            i++;
        for (;i < end; i++){
            if (sequence[i] > root)
                break;
        }
        for (int j = i; j < end; j++){
            if (sequence[j] < root)
                return false;
        }
        return helpVerify(sequence,start,i-1) && helpVerify(sequence,i,end-1);
    }
}

Note: 要考虑到子树为空的特殊情况。

 

相关题目

       输入一个整数数组,判断该数组是不是某二叉搜索树的前序遍历结果。 这和前面问题的后序遍历很类似,只是在前序遍历得到的序列中,第一个数字是根节点的值。
 
原文地址:https://www.cnblogs.com/HuangYJ/p/13498753.html