Sword33——二叉搜索树的后序遍历序列

Sword33——二叉搜索树的后序遍历序列

方法1——递归

  • 思路:树的大部分问题都可以使用递归解决。
    • 首先确定当前树的根节点即为右边界j对应的数字
    • 使用一个下标指针从左往右遍历
      • 找到第一个比根节点大的值,即为右子树的第一个节点mid下标
    • 接着从左往右遍历,判断其右子树节点是否全部大于根节点
    • 当右子树节点部分出现不满足情况,则指针下标无法到右边界j,即返回false
    • 否则则继续对其左子树和右子树递归,左右子树分界即为找到的右子树第一个节点mid下标
  • 特殊情况与临界分析:无
  • 终止条件:无
  • 步骤:
    • 开启递归
    • 递归方法
      • 参数:后序遍历数组、构造当前树的左右边界
      • 终止条件:当左边界left大于等于右边界right时(似乎最多为等于,考虑到数组为空情况,将会出现left大于right情况),证明此时符合返回true
      • (明确右边界right对应即为当前树的根节点,因为后序遍历为左-右-根)
      • 定义指针下标,从左边界left开始
      • 循环条件:从左边界left向右遍历,对应值小于右边界right对应根节点的值
      • while循环
        • 指针下标右移
      • 记录while循环退出时第一个大于根节点的值下标mid,也就是右子树的第一个节点,即当前树左右子树的分隔点
      • 循环条件:从mid开始继续向右遍历,对应值大于右边界right对应根节点的值
      • while循环
        • 指针下标右移
      • 判断指针下标是否已达到右边界right,未到则代表右子树中存在比根节点小的节点,即不符合条件,返回false(可与最后一步合并)
      • 继续对左右子树依次进行递归判断
        • 左子树:左边界为left,右边界为mid - 1
        • 右子树:左边界为mid,右边界为right - 1
    public boolean verifyPostorder(int[] postorder) {
        // 开启递归
        return recur(postorder, 0, postorder.length - 1);
    }
	// 递归方法
	private boolean recur(int[] postorder, int left, int right) {
        // 递归终止条件
        if (left >= right) {
            return true;
        }
        // 定义指针下标
        int point = left;
        // while循环
        while (postorder[point] < postorder[right]) {
            // 指针下标后移
            point++;
        }
        // 记录当前右子树的第一个节点下标
        int mid = point;
        // while循环
        while (postorder[point] > postorder[right]) {
            // 指针下标后移
            point++;
        }
        // 当指针下标未达到右边界,直接返回不符合
        // 继续对左右子树递归
        return (point == right) && recur(postorder, left, mid - 1) && recur(postorder, mid, right - 1); 
    }

方法1——递归

方法2——辅助栈

注意:此方法晦涩难懂,且时间耗费更长,有需要了解即可

  • 思路:后序遍历为左-右-根,其逆序之后顺序为根-右-左。
    • 假设当前树是以Integer.MAX_VALUE为根节点的左子树(为了符合左子树节点小于根节点,首先设置root为Integer最大值),判断数组中元素(即左子树节点)应该均小于根节点root
    • 首先将当前树的根节点和右子树节点入栈,即只留下左子树节点
    • 当遍历到左子树节点,则证明当前树的右子树部分是符合的,弹出栈中所有元素(栈底最后一个元素才为当前树的根节点)重新设置root节点,重新开始上述步骤即可
  • 特殊情况与临界分析:
  • 终止条件:
  • 步骤:
    • 定义辅助栈,便于存储节点
    • 定义根节点
    • for循环遍历数组
      • 确定当前元素是否符合二叉树定义,即左子树节点比根节点要小
      • while循环判断栈是否非空,且栈顶元素大于当前元素,符合即代表此时已遍历到左子树的第一个元素,出栈的栈底元素即为左子树的根节点
      • 将当前元素压入栈中
    • 如果在for循环中都符合二叉树定义,则最后返回true
    public boolean verifyPostorder(int[] postorder) {
        // 定义辅助栈
        Deque<Integer> stack = new LinkedList<>();
        // 定义根节点
        int root = Integer.MAX_VALUE;
        // for循环
        for (int i = postorder.length - 1; i >= 0; i--) {
            // 确定左子树节点比根节点要小
            if (postorder[i] > root) {
                return false;
            }
            // while循环找到栈顶元素
            while (!stack.isEmpty() && stack.peek() > postorder[i]) {
                root = stack.pop();
            }
            // 将当前元素入栈
            stack.push(postorder[i]);
        }
        // 返回true
        return true;
    }

方法2——辅助栈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值