java数据结构与算法之二叉树的最大宽度和最大深度问题

①、最大深度问题

  • 求二叉树的最大深度,最常见的无非两种方式
  • 第一种是,以【宽度优先遍历】统计树的层数,树有多少层,那么树就有多高
  • 第二种是,以【深度优先遍历】,以我们上面讲的【二叉树通用套路】,每个节点都可以向他的左右孩子要信息来求解

深度优先求树的最大高度解法

/**
 * 以深度优先,求二叉树的高度
 */
public static int height(TreeNode treeNode) {
    if (treeNode == null) {
        return 0;
    }
    // 分别获取到左右孩子的树高度(问左右孩子要信息)
    int left = height(treeNode.left);
    int right = height(treeNode.right);

    // 整合所有孩子的高度,以当前节点为头的二叉树的树高为左右孩子中最高的高度 + 1
    return Math.max(left, right) + 1;
}

宽度优先求树的最大深度解法

/**
 * 以宽度优先求二叉树的高度
 * 该二叉树有多少层,那么就说明该树有多高,根据这个特性我们就可以使用宽度优先遍历来计算该树的层数,进而求得树的高度
 */
public static int height2(TreeNode treeNode) {
    if (treeNode == null) {
        return 0;
    }
    LinkedList<TreeNode> queue = new LinkedList<>();
    HashMap<TreeNode, Integer> levelMap = new HashMap<>();
    // 当前层
    int currentLevel = 1;
    queue.addLast(treeNode);
    levelMap.put(treeNode, 1);

    while (!queue.isEmpty()) {
        TreeNode poll = queue.pollFirst();
        // 节点出现了跨层,那么就把层数++
        if (currentLevel != levelMap.get(poll)) {
            currentLevel++;
        }
        // 处理孩子节点
        if (poll.left != null) {
            levelMap.put(poll.left, levelMap.get(poll) + 1);
            queue.addLast(poll.left);
        }
        if (poll.right != null) {
            levelMap.put(poll.right, levelMap.get(poll) + 1);
            queue.addLast(poll.right);
        }
    }

    return currentLevel;
}

②、最大宽度问题

  • 最大宽度问题,最常使用的解法便是【借助队列】 + BFS,一层一层的遍历二叉树,并且记录好每一层的节点个数,节点个数最多的层,便是该树的最大宽度
  • 通常我们使用的是【hash表 + BFS】来记录下每个节点所处的层数
  • 然后使用BFS宽度优先遍历法,去统计每层的节点个数(每一层的宽度),最宽的那一层便是二叉树的最大宽度
public static int width(TreeNode treeNode) {
    if (treeNode == null) {
        return 0;
    }
    //队列
    LinkedList<TreeNode> queue = new LinkedList<>();
    // 存放层级关系的map
    HashMap<TreeNode, Integer> levelMap = new HashMap<>();
    // 树的最大宽度
    int maxWidth = -1;
    // 当前所在的层
    int currentLevel = 1;
    // 当前层的节点数量
    int currentLevelCount = 0;
    queue.addLast(treeNode);
    // 先记录上每个节点所处的层
    levelMap.put(treeNode, 1);

    while (!queue.isEmpty()) {
        TreeNode poll = queue.pollFirst();
        // 节点没有跨层
        if (currentLevel == levelMap.get(poll)) {
            currentLevelCount++;
        } else {
            // 遇到第一个跨层的节点,先【结算上一层】节点个数和最大值,然后【重置当前层的节点个数为1个】
            maxWidth = Math.max(maxWidth, currentLevelCount);
            currentLevelCount = 1;
            currentLevel++;
        }
        // 左右孩子分别入队列,并记录他们所处的层数
        if (poll.left != null) {
            levelMap.put(poll.left, levelMap.get(poll) + 1);
            queue.addLast(poll.left);
        }
        if (poll.right != null) {
            levelMap.put(poll.right, levelMap.get(poll) + 1);
            queue.addLast(poll.right);
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值