[itint5]根据前序后序遍历统计二叉树

本文介绍了一种通过前序遍历和后序遍历来计算二叉树数量的方法。利用递归思想,通过比较前序遍历和后序遍历的特性来确定根节点及其左右子树的位置,从而实现对不同二叉树形态的有效计数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.itint5.com/oj/#28

这题有意思。一开始还想不清楚,看了解释,很棒。

这个题目的特殊之处是所有节点的值都是不一样的. 所以递归过程可以大大简化. 先看两种遍历的性质:

pre-order: root, left *************, right #########

post-order: **************left, ########right, root

所以 pre-order 的第一个元素一定等于 post-order 的最后一个元素. 然后在post-order中由前往后找, 找出等于pre-oder中第二个元素的位置, 也就是 left 的位置. 如果post-order中的这个位置不是倒数第二个, 说明左右子树都非空, 那么对左右子树递归调用后用乘法原理. 如果是倒数第二个, 说明有一个子树为空, return的值就是 2*递归调用非空子树.

int countHelper(vector<int>& preorder, vector<int>& postorder, int preA, int preB, int postA, int postB) {
    if (preA > preB || postA > postB) return 0;
    if (preA == preB && postA == postB && preorder[preA] == postorder[postB]) return 1;
    // preB > preA && postB > postA
    // assert(preorder[preA] == postorder[postB]

    if (preorder[preA+1] == postorder[postB-1]) { // right tree or left tree is null
        return 2 * countHelper(preorder, postorder, preA+1, preB, postA, postB-1);
    } else { // right tree and left tree both exists
        int rightInPreOrder = -1;
        for (int i = preA+2; i < preorder.size(); i++) {
            if (preorder[i] == postorder[postB-1]) {
                rightInPreOrder = i;
                break;
            }
        }
        int leftInPostOrder = -1;
        for (int i = postB-2; i >= 0; i--) {
            if (postorder[i] == preorder[preA+1]) {
                leftInPostOrder = i;
                break;
            }
        }
        return countHelper(preorder, postorder, preA+1, rightInPreOrder-1, postA, leftInPostOrder) *
               countHelper(preorder, postorder, rightInPreOrder, preB, leftInPostOrder+1, postB-1);
    }
    
}

int countValidTrees(vector<int>& preorder, vector<int>& postorder) {
    // assert(preorder.size() == postorder.size());
    return countHelper(preorder, postorder, 0, preorder.size()-1, 0, postorder.size()-1);
}

  

转载于:https://www.cnblogs.com/lautsie/p/3528926.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值