zoukankan      html  css  js  c++  java
  • 二叉树的宽度问题

    思路:

    刚开始理解错了题目:以为求每一层的节点个数,然后求最大值。

    于是有了:所有层中的最大节点数(声明了一个class包含了每个节点的层数,然后用Deque 模拟队列进行一次层次遍历,每次插入新的节点时,将父节点的layer+1赋值给子节点,然后将当前层的节点数+1,这里用了一个数组layers记录(长度我没有算,后面其实可以计算二叉树的深度O(logn),定义数组长度),最后可以遍历数组layers,找最大值)

    class Solution {
            class NodeLayer{
                TreeNode treeNode;
                int layer;
                public NodeLayer(TreeNode treeNode, int layer){
                    this.treeNode = treeNode;
                    this.layer = layer;
                }
            }
            // 先计算每一层的所有数量,取最大值
            public int widthOfBinaryTree(TreeNode root) {
                if(root == null){
                    return 0;
                }
                return  maxWidth(root);
            }
            public int maxWidth(TreeNode root){
                // 假设最大有100层。
                int[] layers = new int[100];
                Deque<NodeLayer> deque = new ArrayDeque<>();
                deque.addLast(new NodeLayer(root,0));
                // 先写一个层次遍历
                while(!deque.isEmpty()){
                    NodeLayer temp = deque.pollFirst();
                    // System.out.println(temp.treeNode.val);
                    layers[temp.layer]+=1;
    
                    if(temp.treeNode.left != null){
                        deque.addLast(new NodeLayer(temp.treeNode.left,temp.layer+1));
                    }
                    if(temp.treeNode.right != null){
                        deque.addLast(new NodeLayer(temp.treeNode.right,temp.layer+1));
                    }
                }
                int max = 0;
                for(int i=0; i<10; i++){
                    max = Math.max(max,layers[i]);
                }
                return max;
            }
        }

    发现问题后,我第一时间想到了双指针,每次指向左和右

    还是有问题,因为找不到下一层的第一个节点,最后想到了利用index找

    于是有了下面的方法。

    1.首先我在之前的类中添加定义了一个值index 用于保存当前节点的index,这样我只需找到每一层最前和最后的index,相减加一即可得到最终解。

    我利用一个数组layers_width[]保存每一层的宽度(当换层的时候,也就是上一个节点的layer与当前节点的layer不一样的时候,更新上一层的宽度和当前层的index),

    用上一个节点(lastNode.index - layers_width[lastNode.layer] +1)上一层第一个节点的index 与 最后一个节点的index的差加一。然后将当前节点temp的index保存到当前层的位置:layers_width[temp.layer] = temp.index,下次就只需要用最后一个节点减就可以了。

    2.中途出现了一个bug,是因为我将最后的边界条件放在了while里面,我判断deque为null时启动,但是该条件不止触发了一次,排查了很久。

    3.完成后我对初始化的数组进行了优化:计算二叉树的深度来代替layers_width的长度(之前是随便设置了一个大数值,太小的话有的测试用例不过,太大浪费空间和时间)。后来发现不需要使用数组保存,只需要定义一个变量保存上一层的第一个节点的index:lastLayerFirstIndex(也不用计算二叉树深度了)。每次换层只需要比较大小并更新上一层的长度(lastNode.index - lastLayerFirstIndex +1)当前最大长度max,然后更新lastLayerFirstIndex 为当前节点temp的index。

    4.循环结束后,再更新一次max。这是由于最后一个节点如果没有换层,导致最后一层的宽度没有计算,所以需要在循环外进行一次更新max。

    class Solution {
        class NodeLayer{
            TreeNode treeNode;
            int layer;
            int index;
            public NodeLayer(TreeNode treeNode, int layer, int index){
                this.treeNode = treeNode;
                this.layer = layer;
                this.index = index;
            }
        }
     
        public int widthOfBinaryTree(TreeNode root) {
            if(root == null){
                return 0;
            }
            return  maxWidth(root);
        }
        public void maxDepth(TreeNode node, int depth, int[] max){
            if(node.left == null && node.right == null){
                max[0] = Math.max(max[0], depth);
            }
            if(node.left != null){
                maxDepth(node.left, depth+1, max);
            }
            if(node.right != null){
                maxDepth(node.right, depth+1, max);
            }
        }
        public int maxWidth(TreeNode root){
            // // 先求深度
            // int[] depth = new int[1];
            // maxDepth(root, 1, depth);
            // //深度
            // int len = depth[0]; 
            // // int len = 4000;
                
            // int[] layers_width = new int[len];
            int lastLayerFistIndex=0;
    
            Deque<NodeLayer> deque = new ArrayDeque<>();
            NodeLayer first = new NodeLayer(root,0,0);
            deque.addLast(first);
            
            int max = 1;
            // 定义一个指向上一个节点的指针
            NodeLayer lastNode=first;
            // 先写一个层次遍历
            while(!deque.isEmpty()){
                NodeLayer temp = deque.pollFirst();
    
                // 判断是否换层。如果换层就更新层宽度,最后一个节点的坐标减第一个的坐标
                // System.out.println(temp.layer);
                if(lastNode.layer != temp.layer){
                    
                    // // 更新上一层宽度
                    // layers_width[lastNode.layer] = lastNode.index-layers_width[lastNode.layer] +1;
                    // max = Math.max(lastNode.index-layers_width[lastNode.layer] +1,max);
                    max = Math.max(lastNode.index-lastLayerFistIndex +1,max);
                    // 更新当前层第一个节点
                    // layers_width[temp.layer] = temp.index;
                    lastLayerFistIndex = temp.index;
    
                }
                lastNode = temp;
                if(temp.treeNode.left != null){
                    deque.addLast(new NodeLayer(temp.treeNode.left,temp.layer+1,temp.index*2+1));
                }
                if(temp.treeNode.right != null){
                    deque.addLast(new NodeLayer(temp.treeNode.right,temp.layer+1,temp.index*2+2));
                }
            }
            // 如果最后一次没有发生层级改变
            // layers_width[lastNode.layer] = lastNode.index-layers_width[lastNode.layer] +1;
            // max = Math.max(lastNode.index-layers_width[lastNode.layer] +1,max);
            max = Math.max(lastNode.index-lastLayerFistIndex +1,max);
     
            // for(int i=0; i<len ;i++){       
            //     // System.out.print(layers_width[i]+" ");
            //     max = Math.max(max,layers_width[i]);
            // }
            return max;
        }
    }
  • 相关阅读:
    Html禁止粘贴 复制 剪切
    表单标签
    自构BeanHandler(用BeansUtils)
    spring配置中引入properties
    How Subcontracting Cockpit ME2ON creates SD delivery?
    cascadia code一款很好看的微软字体
    How condition value calculated in sap
    Code in SAP query
    SO Pricing not updated for partial billing items
    Javascript learning
  • 原文地址:https://www.cnblogs.com/wsZzz1997/p/14701559.html
Copyright © 2011-2022 走看看