【剑指offer】JZ33 二叉搜索树的后序遍历序列

文章讲述了如何通过递归和辅助栈的方法判断一个整数数组是否为某个二叉搜索树的后序遍历结果,强调了查找根节点和利用栈来模拟后序遍历过程的重要性。

1 问题

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

数据范围: 节点数量 0≤n≤1000 ,节点上的值满足 1≤val≤10 ,保证节点上的值各不相同
要求:空间复杂度 O(n) ,时间时间复杂度 O(n^2)

提示:
1.二叉搜索树是指父亲节点大于左子树中的全部节点,但是小于右子树中的全部节点的树。
2.该题我们约定空树不是二叉搜索树
3.后序遍历是指按照 “左子树-右子树-根节点” 的顺序遍历
4.参考下面的二叉搜索树,示例 1

在这里插入图片描述
示例1
输入:[1,3,2]
返回值:true
说明:是上图的后序遍历 ,返回true

示例2
输入:[3,1,2]
返回值:false
说明:不属于上图的后序遍历,从另外的二叉搜索树也不能后序遍历出该序列 ,因为最后的2一定是根节点,前面一定是孩子节点,可能是左孩子,右孩子,根节点,也可能是全左孩子,根节点,也可能是全右孩子,根节点,但是[3,1,2]的组合都不能满足这些情况,故返回false

示例3
输入:[5,7,6,9,11,10,8]
返回值:true

2 问题

这题直接不会,没想到从最后(根节点)开始遍历

官方解

  1. 递归

第一步:找到数组最后一位,即根节点root。
紧接着
第二步:获取整个数组的长度,开始遍历并与root值比较,第一个大于root的值就是左右子树的分界点。
第三步:遍历右子树,验证是否符合二叉搜索树的概念;如上图,以12为分界点的右边所有节点都是大于root的,所以是符合二叉搜索树的。
第四步:继续往下递归,查看余下的左右子树是否符合。这里再放一个不符合的数组案例给大家对比一下,数字图标表示步骤:

class Solution:
    def VerifySquenceOfBST(self, sequence):
        if not sequence:
            return False
        len_s = len(sequence)
        root = sequence[len_s - 1]
        index = 0
        for i in range(len_s):
            if sequence[i] >= root:
                index = i
                break
        for j in range(index, len_s):
            if sequence[j] < root:
                return False
        left = True
        if index > 0:
            left = self.VerifySquenceOfBST(sequence[:index])
        right = True
        if index < len_s - 1:
            right = self.VerifySquenceOfBST(sequence[index:-1])
        return left and right
  1. 逆序后序遍历 + 辅助栈

后序遍历是“左节点 —> 右节点 —> 根节点”,那么逆序后序遍历就是👉:“根节点 ----> 右节点 ----> 左节点”。

按照这个思路,上面的示例(👉 [4,8,6,12,16,14,10])我们可以这么拆解(辅助栈只存储递增的节点):

  1. 先把根节点10 添加到辅助栈 ([10]),然后遍历右子树。
  2. 如果右子树存在,那么下一个数一定是 大于根节点的,且它是右子树的根节点(这里就是14),也把它添加到辅助栈中(此时为[10, 14]) ;依次类推,直到下一个数小于(这里就是12)右子树根节点,说明右子树已经遍历结束 (此时辅助栈中有[10,14,16]) 。
  3. 此时的这个小于根节点的数(就是 12),并不一定是左子树的子节点。所以这里需要判断:
  • 先把刚刚压入的右子树节点都弹出栈(即弹出[14, 16]),此时栈只有一个元素(即[10]);
  • 由于栈顶元素(10)小于 12,那么最后出栈的 14 就是这个 12 的父节点,把它也压入栈中,此时栈👉[10,12]。
  1. 下一个数是 6,又是小于当前栈中的栈顶元素 12,说明12没右子树;再次把[10,12]弹出栈,此时栈空。同理最后出栈的 10 就是 6的父节点!又把6 压入栈中,此时栈👉[6]。
  2. 同理后面的 8 ,是比栈顶元素 6 大的,所以入栈[6, 8],且 6是 8的根节点。
  3. 最后的 4 比 [6, 8]小,所以[6, 8]依次出栈;且 4 是 6的左子节点。此时遍历结束,得到二叉搜索树。
class Solution:
    def VerifySquenceOfBST(self, sequence):
        if not sequence:
            return False
        root = float('+inf')
        stack = []
        for i in range(len(sequence)-1, -1, -1):
            if sequence[i] > root:
                return False
            else:
                while stack and stack[-1] > sequence[i]:
                    root = stack.pop()
                stack.append(sequence[i])
        return True

https://www.nowcoder.com/share/jump/9318638301698682851584

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LouHerGetUp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值