代码随想录算法训练营第15天 | 层序遍历 、226.翻转二叉树、101. 对称二叉树

61 阅读5分钟

 层序遍历 

102.二叉树的层序遍历

【思路】:看代码注释

/**
 * Definition for a binary tree node.
 * 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;
 * }
 * }
 */
class Solution {
    // 记录返回的数据结果
    public List<List<Integer>> resList = new ArrayList<List<Integer>>();

    public List<List<Integer>> levelOrder(TreeNode root) {
        // 迭代遍历
        // iterateOrder(root);
        recursionOrder(root, 0);
        return resList;
    }

    public void iterateOrder(TreeNode node) {
        if (node == null)
            return;
        // 节点队列
        Queue<TreeNode> queue = new LinkedList<>();
        // 将第一个节点加入队列,为第一层
        queue.offer(node);
        // 当队列不为空,保持队列一直有元素,如果没有说明树节点已经访问完了
        while (!queue.isEmpty()) {
            // 记录每层的元素
            List<Integer> itemList = new ArrayList<>();
            // 记录每一层的长度
            int len = queue.size();
            // 遍历每一层的每一个节点,将值加入到itemList中
            while (len-- > 0) {
                TreeNode tempNode = queue.poll();

                itemList.add(tempNode.val);
                // 加入每个节点的左右节点构成新层
                if (tempNode.left != null)
                    queue.offer(tempNode.left);
                if (tempNode.right != null)
                    queue.offer(tempNode.right);
            }
            // 将每层的元素加入到resList
            resList.add(itemList);
        }
    }

    // 递归方式
    public void recursionOrder(TreeNode node, Integer deep) {
        if (node == null)
            return;
        if (resList.size() == deep) {
            // 当层级增加时,list的Item也增加,利用list的索引值进行层级界定
            // 建立一个新空数组加到resList数组中
            List<Integer> itemList = new ArrayList<>();
            resList.add(itemList);
        }
        // 取出空数组,添加节点值
        resList.get(deep).add(node.val);

        recursionOrder(node.left, deep + 1);
        recursionOrder(node.right, deep + 1);
    }
}

107.二叉树的层次遍历 II

思路:将102的resList翻转即可,或者再加入层级数组itemList的时候每次加入到resList头部

199.二叉树的右视图

思路:判断最后一个节点,加入到List中

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Deque<TreeNode> que = new LinkedList<>();

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

        que.offerLast(root);
        while (!que.isEmpty()) {
            int levelSize = que.size();

            for (int i = 0; i < levelSize; i++) {
                TreeNode poll = que.pollFirst();

                if (poll.left != null) {
                    que.addLast(poll.left);
                }
                if (poll.right != null) {
                    que.addLast(poll.right);
                }

                if (i == levelSize - 1) {
                    list.add(poll.val);
                }
            }
        }

        return list;
    }
}

637.二叉树的层平均值

思路:记录每层的总和,再求平均值

class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        // 节点队列
        Queue<TreeNode> queue = new LinkedList<>();
        // 记录元素
        List<Double> resList = new ArrayList<>();
        // 将第一个节点加入队列,为第一层
        if (root == null)
            return resList;
        queue.offer(root);
        // 当队列不为空,保持队列一直有元素,如果没有说明树节点已经访问完了
        while (!queue.isEmpty()) {
            // 记录每一层的长度
            int len = queue.size();
            //记录每一层的总和
            Double sumVal = 0.0;
            // 遍历每一层的每一个节点,将值加入到itemList中
           for (int i = 0; i < len; i++) {
                TreeNode tempNode = queue.poll();

                sumVal += tempNode.val;
                // 加入每个节点的左右节点构成新层
                if (tempNode.left != null)
                    queue.offer(tempNode.left);
                if (tempNode.right != null)
                    queue.offer(tempNode.right);
            }
            // 将每层的元素加入到resList
            resList.add(sumVal / len);
        }
        return resList;
    }
}

429.N叉树的层序遍历

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> list = new ArrayList<>();
        Deque<Node> que = new LinkedList<>();

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

        que.offerLast(root);
        while (!que.isEmpty()) {
            int levelSize = que.size();
            List<Integer> levelList = new ArrayList<>();

            for (int i = 0; i < levelSize; i++) {
                Node poll = que.pollFirst();

                levelList.add(poll.val);

                List<Node> children = poll.children;
                if (children == null || children.size() == 0) {
                    continue;
                }
                for (Node child : children) {
                    if (child != null) {
                        que.offerLast(child);
                    }
                }
            }
            list.add(levelList);
        }

        return list;
    }
}

515.在每个树行中找最大值

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        if(root == null){
            return Collections.emptyList();
        }
        List<Integer> result = new ArrayList();
        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            int max = Integer.MIN_VALUE;
            for(int i = queue.size(); i > 0; i--){
               TreeNode node = queue.poll();
               max = Math.max(max, node.val);
               if(node.left != null) queue.offer(node.left);
               if(node.right != null) queue.offer(node.right);
            }
            result.add(max);
        }
        return result;
    }
}

116.填充每个节点的下一个右侧节点指针

class Solution {
    public Node connect(Node root) {
        Queue<Node> tmpQueue = new LinkedList<Node>();
        if (root != null)
            tmpQueue.add(root);
        while (tmpQueue.size() != 0) {
            int size = tmpQueue.size();
            Node preNode = null;
            for (int index = 0; index < size; index++) {
                Node curNode = tmpQueue.poll();
                //第一个元素preNode要么不赋值,要么和curNode相等
                // if (index == 0) {
                //     preNode = curNode;
                // } else {
                //     preNode.next = curNode;
                //     preNode = curNode;
                // }
                //if( index !=0) {
                //     preNode.next = curNode;
                }
                //     preNode = curNode;
                //上下三种写法都可以
                if (preNode != null)
                    preNode.next = curNode;
                preNode = curNode;

                if (curNode.left != null)
                    tmpQueue.add(curNode.left);
                if (curNode.right != null)
                    tmpQueue.add(curNode.right);
            }
            preNode.next = null;
        }

        return root;
    }
}

117.填充每个节点的下一个右侧节点指针II

思路:和117一模一样

104.二叉树的最大深度

思路:每次遍历的时候记录一下

class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null)   return 0;
        Queue<TreeNode> que = new LinkedList<>();
        que.offer(root);
        int depth = 0;
        while (!que.isEmpty())
        {
            int len = que.size();
            while (len > 0)
            {
                TreeNode node = que.poll();
                if (node.left != null)  que.offer(node.left);
                if (node.right != null) que.offer(node.right);
                len--;
            }
            depth++;
        }
        return depth;
    }
}

111.二叉树的最小深度

思路:遍历每层节点时,判断每个节点的左右节点都是空的,如果是则直接返回当前层数

class Solution {
    public int minDepth(TreeNode root) {
        if (root == null)   return 0;
        Queue<TreeNode> que = new LinkedList<>();
        que.offer(root);
        int depth = 0;

        while (!que.isEmpty())
        {
            int len = que.size();
            //让depth先记录当前层数
            depth++;
            while (len-- > 0)
            {
                TreeNode node = que.poll();
                if (node.left == null && node.right == null ) return depth;
                if (node.left != null)  que.offer(node.left);
                if (node.right != null) que.offer(node.right);
            }
        }
        return depth;
    }
}

题目链接/文章讲解/视频讲解:programmercarl.com/0102.%E4%BA…

 226.翻转二叉树 (优先掌握递归) 

这道题目 一些做过的同学 理解的也不够深入,建议大家先看我的视频讲解,无论做过没做过,都会有很大收获。

//DFS递归
class Solution {
  /**
    * 前后序遍历都可以
    * 中序不行,因为先左孩子交换孩子,再根交换孩子(做完后,右孩子已经变成了原来的左孩子),再右孩子交换孩子(此时其实是对原来的左孩子做交换)
    */
   public TreeNode invertTree(TreeNode root) {
       if (root == null) {
           return null;
       }
       invertTree(root.left);
       invertTree(root.right);
       swapChildren(root);
       return root;
   }

   private void swapChildren(TreeNode root) {
       TreeNode tmp = root.left;
       root.left = root.right;
       root.right = tmp;
   }
}

// //BFS
// class Solution {
//     public TreeNode invertTree(TreeNode root) {
//         if (root == null) {return null;}
//         ArrayDeque<TreeNode> deque = new ArrayDeque<>();
//         deque.offer(root);
//         while (!deque.isEmpty()) {
//             int size = deque.size();
//             while (size-- > 0) {
//                 TreeNode node = deque.poll();
//                 swap(node);
//                 if (node.left != null) deque.offer(node.left);
//                 if (node.right != null) deque.offer(node.right);
//             }
//         }
//         return root;
//     }

//     public void swap(TreeNode root) {
//         TreeNode temp = root.left;
//         root.left = root.right;
//         root.right = temp;
//     }
// }

题目链接/文章讲解/视频讲解:programmercarl.com/0226.%E7%BF…

 101. 对称二叉树 (优先掌握递归)  

先看视频讲解,会更容易一些。 

/**
 * Definition for a binary tree node.
 * 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;
 * }
 * }
 */
class Solution {

    public boolean isSymmetric(TreeNode root) {
        return compare(root.left, root.right);
    }

    private boolean compare(TreeNode left, TreeNode right) {

        if (left == null && right != null) {
            return false;
        }
        if (left != null && right == null) {
            return false;
        }

        if (left == null && right == null) {
            return true;
        }
        if (left.val != right.val) {
            return false;
        }
        // 比较外侧
        boolean compareOutside = compare(left.left, right.right);
        // 比较内侧
        boolean compareInside = compare(left.right, right.left);
        return compareOutside && compareInside;
    }

}

题目链接/文章讲解/视频讲解:programmercarl.com/0101.%E5%AF…

总结

题目好多呀,没想到一次性刷了那么多题,对递归还不是很熟悉,很多种遍历方式有点混乱,回头得再整理一下