二叉树层次遍历相关题目

由于Leetcode上关于层次遍历的题目比较多,所以单独一篇文章来讲解

# 1. 层次遍历相关的题目

102. 二叉树的层序遍历 - M (opens new window)

字节 - 18 , 微软 - 6

107. 二叉树的层序遍历 II - M (opens new window)

103. 二叉树的锯齿形层序遍历 - M (opens new window)

==高频==

637. 二叉树的层平均值- E (opens new window)

429. N 叉树的层序遍历 (opens new window)

微软 - 2


# 102. 二叉树的层序遍历 - M (opens new window)

字节 - 18 , 微软 - 6 , 亚马逊 - 13

二叉树的层次遍历是必须要掌握的,需要用到队列

偷个图

public class Solution{
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList();
        if(root == null){
            return result;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        while(!queue.isEmpty()){
            int size = queue.size();

            List<Integer> level = new ArrayList();

            while(size -- > 0){
                TreeNode node = queue.poll();
                level.add(node.val);

                if(node.left != null){
                    queue.offer(node.left);
                }

                if(node.right != null){
                    queue.offer(node.right);
                }
            }

            result.add(level);
        }

        return result;
    }
}

# 107. 二叉树的层序遍历 II - M (opens new window)

字节- 6 ,微软 - 2

这道题目与102 (opens new window)的差别在于:此题要求是 自底向上的层序遍历

我们采用头插法即可。

public class Solution{
     
     public List<List<Integer>> levelOrderBottom(TreeNode root){
         
         List<List<Integer>> result = new ArrayList();

         if(root == null){
             return result;
         }

         Queue<TreeNode> queue = new LinkedList();
         queue.add(root);

         while(!queue.isEmpty()){
             int size = queue.size();
             List<Integer> level = new ArrayList();

             while(size-- > 0){
                 TreeNode node = queue.poll();
                 level.add(node.val);

                 if(node.left != null){
                     queue.offer(node.left);
                 }

                 if(node.right != null){
                     queue.offer(node.right);
                 }
             }
            // 头插法
             result.add(0,level);
         }

         return result;
     }
}

# 103. 二叉树的锯齿形层序遍历 - M (opens new window)

字节 - 18 , 微软 - 14 ,亚马逊 - 22

此题是Z字形的层次遍历

public class Solution{

    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList();
        if(root == null){
            return root;
        }

        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);

        boolean isReversed =  false;

        while(!queue.isEmpty()){

            int size = queue.size();
            List<Integer> level = new ArrayList();

            while(size-- > 0){
                TreeNode node = queue.poll();
                // 处理 Z字形的关键
                if(isReversed){
                    level.add(0,node.val);
                }else{
                    level.add(node.val);
                }

                if(root.left != null){
                    queue.offer(node.left);
                }

                if(root.right != null){
                    queue.offer(node.right);
                }
            }
            result.add(level);
            isReversed = !isReversed;
        }

        return result;
    }

}


# 637. 二叉树的层平均值- E (opens new window)

public class Solution{
    
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> result = new ArrayList();
        if(root == null){
            return result;
        }

        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);

        while(!queue.isEmpty()){
            int size = queue.size();
            double sum = 0.0;
            // 注意这里采用for循环是一个小技巧,
            for(int i = 0 ;i < size; i ++){
                TreeNode node = queue.poll();

                sum += node.val;

                if(node.left != null){
                    queue.offer(node.left);
                }

                if(node.right != null){
                    queue.offer(node.right);
                }
            }
            result.add(sum/size);
        }

        return result;
    }
}

# 429. N 叉树的层序遍历 (opens new window)

微软 - 2

N叉树相较于二叉树,子树多了而已。但是其遍历的思路是不变的。

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> result = new ArrayList();
        if(root == null){
            return result;
        }

        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);

        while(!queue.isEmpty()){
            int size = queue.size();
            List<Integer> level = new ArrayList();

            while(size-- > 0){
                TreeNode node = queue.poll();
                level.add(node.val);
                // 相较于二叉树,只有这里判断子树的数量不同
                for(TreeNode tmp:node.children){
                    queue.offer(tmp);
                }
            }

            result.add(level);
        }

        return result;
    }
}

# 2.利用层次遍历的性质的题目

111. 二叉树的最小深度 (opens new window)

993. 二叉树的堂兄弟节点 (opens new window)

微软- 4,亚马逊 -4


# 993. 二叉树的堂兄弟节点 (opens new window)

微软- 4,亚马逊 -4

解题思路:使用层序遍历,如果两个结点在同一层,它们就是堂兄弟结点(排除一种情况,那就是“这两个结点的父亲结点相同”)

public class Solution {
    public boolean isCousins(TreeNode root, int x, int y) {
        // 这两个值任意一个都不会出现在根节点
        if(root == null || root.val == x || root.val == y){
            return false;
        }

        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);

        // 定义2个节点
        TreeNode xNode,yNode;
        // 为了判断其父节点是否相同,还需要定义出其父节点
        TreeNode xParent,yParent;

        while(!queue.isEmpty()){
            int size = queue.size();

            while(size -- > 0){
                TreeNode node = queue.poll();
                if(node.left !=  null){
                    queue.offer(node.left);
                    if(node.left.val == x){
                        xNode = node.left;
                        xParent = node;
                    }

                    if(node.right.val == y){
                        yNode = node.right;
                        yParent = node;
                    }
                }

                if(node.right != null){
                    queue.offer(node.right);

                    if(node.right.val == x){
                        xNode = node.right;
                        xParent = node;
                    }

                    if(node.right.val == y){
                        yNode = node.right;
                        yParent = node;
                    }
                }
            }
            /** 这里要处理的逻辑
             * 某一层俩节点都为空,说明不在这一层;
             * 同一层的xNode和yNode有一个为空,则直接返回false;
             * 两个都不为空时,需要判断其父节点是否相同。
            */
            if(xNode == null && yNode == null){
                // 说明x,y都不在这层,不用处理
            }else if(xNode != null && yNode != null){
                // 如果父亲结点不相等,说明是堂兄弟结点
                return xParent == yParent;
            }else{
                // 这里的size == 0表示这一次遍历完毕,只存在xNode或者yNode
                if(size == 0){  
                    return false;
                }
            }
        }

        return false;
    }
}

# 111. 二叉树的最小深度 (opens new window)

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

public class Solution {

    public int minDepth(TreeNode root){
        if(root == null) return 0;

        if(root.left != null && root.right == null){
            return minDepth(root.left) + 1;
        }

        if(root.left == null && root.right != null){
            return minDepth(root.right) + 1;
        }

        return Math.min(minDepth(root.left),minDepth(root.right))+1;
    }
    

广度优先搜索的性质保证了最先搜索到的叶子节点的深度一定最小,当我们找到一个叶子节点时,直接返回这个叶子节点的深度。

public class Solution {

    public int minDepth(TreeNode root){
        if(root == null){
            return 0;
        }

        int depth = 1;

        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);

        while(!queue.isEmpty()){
            int size = queue.size();

            while(size -- >0){
                TreeNode node = queue.poll();
                // 广度优先搜索(层次遍历)的性质保证了最先搜索到的叶子节点的深度一定最小。
                if(node.left == null && node.right == null){
                    return depth;
                }

                if(node.left != null){
                    queue.offer(node.left);
                }

                if(node.right != null){
                    queue.offer(node.right);
                }
            }

            depth += 1;
        }

        return depth;
    }

# 314. 二叉树的垂直遍历 (opens new window)

微软 -3 , 亚马逊 - 5

此题留待日后再解...