剑指 33

博客围绕剑指 Offer 33 二叉搜索树的后序遍历序列题目展开。作者起初思路不全面,多次提交失败,代码逻辑混乱。后明确后续遍历序列特点,即最后一个是根节点,比其小的是左子树,大的是右子树,还给出优化思路及优化后的代码。

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

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

题目:

在这里插入图片描述

思路:

没有考虑全面导致
1.多次提交失败,每次都拿失败的用例去改。。。
2.虽然提交通过,但是代码逻辑混乱,思路不变,代码可以优化

思路:后续遍历序列最后一个必是根节点,从始至终,比其小的为左子树,比其大的为右子树。
假设k为临界值,那么k之后的元素都必须比root大,否则返回false。最后reture 前 && 后 即可
(其实还有,都比根节点小和都比根节点大的情况,这两者直接return length-1即可)

题解:

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        return verify(postorder, 0, postorder.length);
    }

    private boolean verify(int[] postorder, int i, int j) {
        int length = j - i;
        if (length <= 2) {
            return true;
        }
        // 1、只有右子树
        int root = postorder[j - 1];
        int a = -1;
        for (int k = i; k < j; k++) {
            if (postorder[k] > root) {
                a = k;
                break;
            }
        }
        for (int k = a; a!=-1 && k < j; k++) {
            if (postorder[k] < root) {
                return false;
            }
            if (k == j - 1) {
                return verify(postorder,i,j-1);
            }
        }
        // 2、只有左子树
        for (int k = i; k < j; k++) {
            if (postorder[k] < root) {
                continue;
            }
            if (k == j - 1) {
                return verify(postorder, i, j-1);
            }
        }
        // 3、先左子树,后右子树
        int temp = -1;
        for (int k = i; k < j; k++) {
            if (postorder[k] < root && postorder[k + 1] > root) {
                temp = k;
                break;
            }
        }
        if (temp >= i && temp <= j) {
            for (int k = temp + 1; k < j; k++) {
            	// 如果都确定都是右子树了,中间又突然来个左子树节点,那么肯定是错误的
                if (postorder[k] < root) {
                    return false;
                }
            }
            return verify(postorder, i, temp + 1) && verify(postorder, temp + 1, j-1);
        }
        // 必须的一个reture
        return false;
    }
}

优化后的代码:

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        return verify(postorder, 0, postorder.length);
    }
    private boolean verify(int[] postorder, int i, int j) {
        // 如果只有两个值,那么就没有比较的必要了,直接返回ture
        if (j - i <= 2) {
            return true;
        }
        int root = postorder[j - 1];
        // 标识位
        int temp = -1;
        for (int k = i; k < j; k++) {
            if (postorder[k] > root) {
                temp = k;
                break;
            }
        }
        if (temp != -1) {
            for (int k = temp; k < j; k++) {
                if (postorder[k] < root) {
                    return false;
                }
            }
            return verify(postorder, i, temp) && verify(postorder, temp, j-1);
        } else {
            return verify(postorder, i, j - 1);
        } 
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值