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

题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。  中等 

方法一:递归分治  时间复杂度O(n2)  空间复杂度O(n) 

根据搜索二叉树的特性(root.left.val < root.val < root.right.val),以及后续遍历的特性(尾部元素为头节点),可将数组进行如下划分:

对于数组 [i , j],遍历找到首个比j大的元素,则该元素为右子树的头结点

  • 区间[i , mid - 1]为左子树
  • 区间[mid , j - 1]为右子树
  • j为头结点

因为在找右子树的时候,已经证明左区间都比头结点的值小,故仅需要判断右区间与j的关系即可

递归的结束条件:区间长度为1  即 i >= j

def verifyPostorder(postorder):
        """
        :type postorder: List[int]
        :rtype: bool
        """

        def deal(i,j):
            if i >= j:
                return True
            l = 0
            while postorder[l] < postorder[j]:
                l += 1
            mid = l
            while postorder[l] > postorder[j]:
                l += 1
            
            return l == j and deal(i,mid - 1) and deal(mid,j - 1)  这里没有判断值的关系,而是判断索引,即当 l != j时,说明右子树出现比头结点小的,不符合搜索二叉树特性
        return deal(0,len(postorder)-1)

方法二:重建二叉树  时间复杂度O(n)  空间复杂度O(n) 

后序遍历数组的倒序的顺序就变成了头右左的DFS,可以通过这一点重建二叉树,每放置一个节点就pop尾部元素,判断最后序列是否为空

def verifyPostorder(postorder):
        """
        :type postorder: List[int]
        :rtype: bool
        """
        def post(postorder,low,up):
            if postorder == []:
                return 
            
            cur_val = postorder[-1]
            if not (low < cur_val < up):
                return 
            postorder.pop()
            post(postorder,cur_val,up)
            post(postorder,low,cur_val)


        post(postorder,float('-inf'),float('inf'))
        return postorder == []    # 这里注意一点  ==是判断数据中的元素是否相同,而is是判断地址是否相同,即 [] == [] 输出True  [] is [] 输出False,因为 [] 和 []是地址空间不同的两个列表

 


posted @ 2022-07-27 12:21  Liang-ml  阅读(20)  评论(0)    收藏  举报