《剑指offer》面试题55(2)

本文探讨了两种判断二叉树是否平衡的有效方法。一种是从根到叶的深度比较,另一种是采用后序遍历并记录节点深度,仅需一次遍历即可完成整树判断。代码示例使用Java实现。

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

题目:平衡二叉树

输入二叉树的根节点,判断该树是否是平衡二叉树。如果某二叉树的任意节点的左右子树深度之差不超过1,则该树是平衡二叉树。

思路1:

依据平衡二叉树的定义解决。借助于上一题二叉树的深度,从根节点开始逐点判断树的左右子树的深度差值是否满足要求。由于此解法是从根到叶的判断,每一次获取节点有需要从当前节点遍历到叶节点,因此需要多次遍历。

思路2:

如果用后序遍历,那么访问某一个节点时已经访问了它的左右子树。同时,在访问节点时记录下它的深度,并由左右子树的深度推出父亲节点的深度,这样我们就能通过遍历一遍完成整棵树的平衡性判断。
对于某一个子树,需要给出它的平衡性的判断,还要给出它的深度,此处我将平衡性的判断作为返回值,深度通过长度为1的数组传递出去,见boolean isBalanced2Core(TreeNode node,int[] depth)。

基于以上思路,java参考代码如下:

//树节点声明如下:
public class TreeNode<T> {
	T key;
	TreeNode<T> left;
	TreeNode<T> right;
	public TreeNode(T key) {
		this.key=key;
	}
}

public class isBalanced {
    //借助于深度,判断是否是平衡二叉树,由于是从根到叶逐点判断,需要多次遍历树
    public static boolean isBalanced(TreeNode<Integer> node){
        if(node==null)
            return true;
        int left = treeDepth(node.left);
        int right = treeDepth(node.right);
        int diff = left - right;
        if(diff<-1||diff>1)
            return false;
        return isBalanced(node.left)&&isBalanced(node.right);
    }
    public static int treeDepth(TreeNode<Integer> root){
        if(root==null)
            return 0;
        int left = treeDepth(root.left);
        int right = treeDepth(root.right);
        return left>right?(left+1):(right+1);
    }
    
    //用后序遍历,并记录每个节点的深度,从而可以通过一次遍历完成整棵树的判断
    //一边遍历树一边判断每个结点是否具有平衡性。
    public static boolean isBalanced2(TreeNode<Integer> node){
        if(node==null)
            return true;
        return isBalanced2Core(node,new int[]{0});
    }

    public static boolean isBalanced2Core(TreeNode<Integer> node,int[] depth){
        if(node==null){
            depth[0] = 0;
            return true;
        }
        int[] left = new int[]{0};
        int[] right = new int[]{0};
        boolean bleft=isBalanced2Core(node.left,left);//左子树判断
        boolean bright=isBalanced2Core(node.right,right);//右子树判断
        if(bleft&&bright){
            int diff = left[0]-right[0];
            if(diff<=1&&diff>=-1){
                depth[0] = 1+(left[0]>right[0]?left[0]:right[0]);
                return true;
            }
            else
                return false;
        }
        return false;
    }
    public static void main(String[] args){
        TreeNode<Integer> root = new TreeNode<>(1);
        root.left = new TreeNode<>(2);
        root.left.left = new TreeNode<>(4);
        root.left.right = new TreeNode<>(5);
        root.left.right.left = new TreeNode<>(7);
        root.right = new TreeNode<>(3);
        root.right.right = new TreeNode<>(6);
        System.out.println(isBalanced(root));
        System.out.println(isBalanced2(root));
    }
}

测试用例:

a.功能测试(平衡的二叉树;不是平衡的二叉树;二叉树所有节点都没有左或右子树)。
b.特殊输入测试(二叉树中只有一个节点;二叉树的头节点为nullptr指针)。

参考:

https://www.jianshu.com/p/59db1f0e6ca9

资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 HttpServletRequestWrapper 是 Java Servlet API 中的一个工具类,位于 javax.servlet.http 包中,用于对 HttpServletRequest 对象进行封装,从而在 Web 应用中实现对 HTTP 请求的拦截、修改或增强等功能。通过继承该类并覆盖相关方法,开发者可以轻松地自定义请求处理逻辑,例如修改请求参数、添加请求头、记录日志等。 参数过滤:在请求到达处理器之前,可以对请求参数进行检查或修改,例如去除 URL 编码、过滤敏感信息或进行安全检查。 请求头操作:可以修改或添加请求头,比如设置自定义的 Content-Type 或添加认证信息。 请求属性扩展:在原始请求的基础上添加自定义属性,供后续处理使用。 日志记录:在处理请求前记录请求信息,如 URL、参数、请求头等,便于调试和监控。 跨域支持:通过添加 CORS 相关的响应头,允许来自不同源的请求。 HttpServletRequestWrapper 通过继承 HttpServletRequest 接口并重写其方法来实现功能。开发者可以在重写的方法中添加自定义逻辑,例如在获取参数时进行过滤,或在读取请求体时进行解密。当调用这些方法时,实际上是调用了包装器中的方法,从而实现了对原始请求的修改或增强。 以下是一个简单的示例,展示如何创建一个用于过滤请求参数的包装器: 在 doFilter 方法中,可以使用 CustomRequestWrapper 包装原始请求: 这样,每当调用 getParameterValues 方法时,都会先经过自定义的过滤逻辑。 HttpServletRequestWrapper 是 Java Web 开发中一个强大的工具,它提供了灵活的扩展性,允许开发者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值