662_二叉树最大宽度
package 二叉树.BT; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Queue; /** * https://leetcode-cn.com/problems/maximum-width-of-binary-tree/ * * @author Huangyujun * */ public class _662_二叉树最大宽度 { public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() { } TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } //层序遍历(有bug:来自于,无法应对null的中间结点)(不对的),使用map无法做到,需要像官网那样封装一个类(标记结点位置的) //本代码逻辑还有另外一个bug://没有把null的情况也一起计算进去【错误最根本原因】 // public int widthOfBinaryTree(TreeNode root) { // // 根结点自己一个时,长度为0 // if (root == null) // return 0; // if (root.left == null && root.right == null) // return 0; // int width = 0; // Queue<TreeNode> queue = new LinkedList<>(); // queue.offer(root); // int pos = 1; // int left = 0; // int right = 0; // int levelSize = 1; // //为啥不能使用map了(如果是这样,进入当前层时,找不着当前层的第一个结点) // Map<TreeNode, Integer> map = new HashMap<TreeNode, Integer>(); // map.put(root, pos); // while (!queue.isEmpty()) { // // 拿到当前结点 // TreeNode node = queue.poll(); // levelSize--; // // 该层出现的最左位置 // if (node.left != null) { // queue.offer(node.left); //// left++;// 左边位置往左移动 //// 添加最左的位置(位置信息等于 node 的 2 倍) // map.put(node.left, map.get(node) * 2); // } // // 该层出现的最右位置 // if (node.right != null) { // queue.offer(node.right); //// right++; // map.put(node.right, map.get(node) * 2); // } // if(levelSize == 0) { // //即将进入下一层 // //获取到当前层的最左边,最右边 // for(int i = 0; i < map.size(); i++) { //// left = Math.min(left, map.get) // } // levelSize = queue.size(); // } // } // // return width; // } /** * 核心思路是位置化(坐标化结点~ 下一个结点(咱只需拿到最左的那个结点,当进入下一层便知道了)位置 i = 2 * i) * (用 键值对标记【结点, 位置】,而不是官网给的包装成一个类(含有深度和位置的结点)) * * 思路是:遍历到结点(就给该结点标注一个位置),该位置信息直接存放到结点的val中 而结点位置:等于 2 * i (i 是 上一层(父元素位置)) * 咱需要定义一个变量来判断结点进入下一层了(depth),从而更新left(最左位置) 然后 (遍历到的当前位置 - 最左位置) 不断更新找到最大位置 * * @author Huangyujun * */ class AnnotatedNode { TreeNode node; int depth, pos; AnnotatedNode(TreeNode n, int d, int p) { node = n; depth = d; pos = p; } // 突破点在于标记最左结点位置 // 通过公式: 下一层的结点位置 2 * i (i 是上一层的) public int widthOfBinaryTree(TreeNode root) { Queue<AnnotatedNode> queue = new LinkedList(); queue.add(new AnnotatedNode(root, 0, 0)); int curDepth = 0, left = 0, ans = 0; while (!queue.isEmpty()) { AnnotatedNode a = queue.poll(); if (a.node != null) {//很巧妙的把null的情况也一起计算进去 queue.add(new AnnotatedNode(a.node.left, a.depth + 1, a.pos * 2)); queue.add(new AnnotatedNode(a.node.right, a.depth + 1, a.pos * 2 + 1)); if (curDepth != a.depth) { curDepth = a.depth; left = a.pos; } ans = Math.max(ans, a.pos - left + 1); } } return ans; } } }