102. 二叉树的层序遍历(10) |226. 翻转二叉树 |101. 对称二叉树(2) 【算法学习笔记】

101 阅读3分钟

今日任务
102. 二叉树的层序遍历10
226. 翻转二叉树
101. 对称二叉树2
代码随想录

102. 二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

思考:1:和之前的题目不一样,这是广度优先遍历,遍历方式和深度优先的遍历方式不一样,使用队列来完成操作。2:因为是层序遍历,需返回每层的元素,所以需要定义len来确定每层的元素个数,相当于通过访问下一层有几个结点来确定下一层的元素个数。

🍅 借助队列(迭代)解法,即借用队列来完成对二叉树的层序遍历

class Solution {
    public List<List<Integer>> reslist = new ArrayList<List<Integer>>();  //定义二维数组
    public List<List<Integer>> levelOrder(TreeNode root) {
        levelorder(root);
        return reslist;
    }
    public void levelorder(TreeNode root){
        if (root==null) return;
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        que.offer(root); //把二叉树入队

        while(!que.isEmpty()){
            List<Integer> list = new ArrayList<>(); //定义单层数组
            int len = que.size(); //定义len用来控制每层循环
            while(len>0){
                TreeNode node = que.poll();   //提取队里的元素
                list.add(node.val);    //加入到一维数组里

                //入队操作
                if(node.left !=null){
                    que.offer(node.left);
                }
                if(node.right !=null){
                    que.offer(node.right);
                }
                len--;

            } 
        reslist.add(list);
        }
    }
}

107. 二叉树的层序遍历 II

这道题在上一题的基础上,用list类的collections.reverse()反转即可

199. 二叉树的右视图

这道题要注意的是返回一维数组,还有len不用--。。
这里写下深度优先遍历的解法(dfs),这个解法比较巧妙的是用深度来捕捉每层的第一个元素,还有这个深度遍历的顺序是中右左。

class Solution {
    List<Integer> res = new ArrayList<>();
    public List<Integer> rightSideView(TreeNode root) {
        dfs(root,0);
        return res;
    }
    public void dfs(TreeNode root, int deepth){
        if (root == null) {
            return;
        }
        if(deepth == res.size()){
            res.add(root.val);
        }
        deepth++;
        dfs(root.right,deepth);
        dfs(root.left,deepth);
        
    }
}

637. 二叉树的层平均值

这道题新增加一个sum把每层的结点加起来就好。这道题如果用BFS来做的话求和有点麻烦

429. N 叉树的层序遍历

这道题的数据结构类型是N叉树,它的孩子都是Node结点,入队操作用for入队就行。

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

要注意空指针的情况,也就是root的值为null。

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

这道题注意返回的是Node,所以只要在每层遍历修改非最后一个结点的next指针就行。dfs解法理解不来。

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

这道题和上一题一样

104. 二叉树的最大深度

定义深度,在每次遍历加1,返回深度即可

111. 二叉树的最小深度

在上题的基础上当左右子树都为空时,返回深度deep即可

226. 翻转二叉树

第一种解法是迭代(bfs),在遍历的基础上加上左右子树的交换即可。 这边贴下递归的代码

//先序遍历
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        reverse(root);
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }
    public void reverse(TreeNode root) {
        TreeNode node = root.left;
        root.left = root.right;
        root.right = node;           
    }
}

101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

第一种解法递归采用的是后序遍历,因为只有先判断左边和右边结点是否对称,最后判断中间结点才可以判断是否是对称二叉树。第二种解法迭代注意入队顺序即可。

递归解法

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return compare(root.left,root.right);
    }
    public boolean compare(TreeNode left,TreeNode right){
        if (left == null && right == null) {
            return true;
        }
        if (left == null || right == null || left.val != right.val) {
                return false;
        }
        boolean compareOutside = compare(left.left,right.right);
        boolean compareInside = compare(left.right,right.left);
        return compareInside && compareOutside;
    }
}

迭代解法

class Solution {
    public boolean isSymmetric(TreeNode root) {
        Queue<TreeNode> deque = new LinkedList<>();
        deque.offer(root.left);
        deque.offer(root.right);
        while (!deque.isEmpty()) {
            TreeNode leftNode = deque.poll();
            TreeNode rightNode = deque.poll();
            if (leftNode == null && rightNode == null) {
                continue;
            }
//            if (leftNode == null && rightNode != null) {
//                return false;
//            }
//            if (leftNode != null && rightNode == null) {
//                return false;
//            }
//            if (leftNode.val != rightNode.val) {
//                return false;
//            }
            // 以上三个判断条件合并
            if (leftNode == null || rightNode == null || leftNode.val != rightNode.val) {
                return false;
            }
            // 这里顺序与使用Deque不同
            deque.offer(leftNode.left);
            deque.offer(rightNode.right);
            deque.offer(leftNode.right);
            deque.offer(rightNode.left);
        }
        return true;
    }
}