剑指offer - 二叉搜索树的后序遍历序列 - python

164 阅读2分钟

二叉查找树(Binary Search Tree) ,(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

题目描述:

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

思路:

  • 法1: 后序遍历:左-右-根,后序遍历序列的最后一个是根节点,前面的分别是左子树节点序列和右子树节点序列。根据二叉搜索本身的性质,左子树所有节点的值都小于根节点的值,右子树所有结点的值都大于根节点的值。因此,从头依次判断前半部分元素是否都小于突变后部分的元素,突变后部分的元素是否都大于根节点。

  • 法2:由法1的叙述可知,根节点为 s e q u e n c e [ − 1 ] sequence[-1] sequence[−1],因此可以在 s e q u e n c e [ : − 1 ] sequence[:-1] sequence[:−1]中寻找第一个大于根节点的元素的索引,然后将其划分为left和right两部分。将两部分排序后比较 l e f t [ − 1 ] left[-1] left[−1]和 r i g h t [ 0 ] right[0] right[0]即可:

    • 如果 l e f t [ − 1 ] < r i g h t [ 0 ] left[-1] < right[0] left[−1]<right[0],返回True
    • 否则返回False
  • 递归法:

    • 确定根节点root;
    • 遍历序列(除去root结点),找到第一个大于root的位置,则该位置左边为左子树,右边为右子树;
    • 遍历右子树,若发现有小于root的值,则直接返回false;
    • 分别判断左子树和右子树是否仍是二叉搜索树

AC代码

# -*- coding:utf-8 -*-
class Solution:
    def VerifySquenceOfBST(self, sequence):
        # write code here
        if sequence == []:
            return False
        
        if len(sequence) == 1:
            return True
        
        root = sequence[-1]
        left_right = sequence[:-2]
        
        for i in range(len(left_right)):
            if left_right[i] > root:
                for n in left_right[i:]:
                    if n < root:
                        return False
                return True

        return True 

最值比较法

# -*- coding:utf-8 -*-
class Solution:
    def VerifySquenceOfBST(self, sequence):
        # write code here
        if sequence == []:
            return False
        if len(sequence) == 1:
            return True
        root = sequence[-1]

        s = sequence[:-1]
        index = -1
        r = []
        for i in range(len(s)):
            if s[i] > root:
                for n in s[i:]:
                	# 如果可能的右子树部分出现小于root的值,直接返回False
                    if root > n:
                        return False
                r.append(i)
                index = i
                break
        # 如果只有左子树,直接返回True
        if r == []:
            return True
		
        left = sorted(sequence[:index])
        right = sorted(sequence[index:-1])

        if left == [] or right == []:
            return True
        if left[-1] < right[0]:
            return True
        else:
            return False

递归法:

class Solution:
    def VerifySquenceOfBST(self, sequence):
        # write code here
        if sequence is None or len(sequence) == 0:
            return True
        
        # 首先找到根节点
        root = sequence[-1]
        n = len(sequence)
        # 左子树结点值都小于根节点
        i = 0
        for i in range(n):
            if sequence[i] > root:
                break
        # 右子树节点值都大于根节点
        for j in range(i, n - 1):
            if sequence[j] < root:
                return False
        # 判断左子树是不是二叉搜索树
        left = True
        if i > 0:
            left = self.VerifySquenceOfBST(sequence[:i])
        right = True
        if i < n - 1:
            right = self.VerifySquenceOfBST(sequence[i:-1])
        
        return left and right