【代码随想录Day14】二叉树遍历

层序遍历

102 二叉树的层序遍历

https://leetcode.cn/problems/binary-tree-level-order-traversal/

BFS已经写熟了,由于是输出List>而不是直接打印,所以可以用dfs三个顺序遍历都可以,找到所在层,在该层所在list里添加。

class Solution {
    public List> levelOrder(TreeNode root) {
        List> result = new ArrayList<>();
        dfs(root, result, 0);
        return result;
    }
    private void dfs(TreeNode root, List> result, int depth) {
        if (root == null) return;
        if (result.size() < depth + 1) result.add(new ArrayList<>());  // bug  if(result.get(depth) == null) 会out of bound
        result.get(depth).add(root.val);
        dfs(root.left, result, depth + 1);
        dfs(root.right, result, depth + 1);
    }
}

107 二叉树的层次遍历 II bottom up倒着输出的

https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/description/

关键点是 List用LinkedList,每个新层放在index=0的头部,容易出bug的地方在dfs方法里,计算所在node要放在哪个list需要从后向前(即从root向下)数index.

class Solution {  // dfs
    public List> levelOrderBottom(TreeNode root) {
        List> result = new LinkedList<>();
        dfs(root, result, 0);
        return result;
    }
    private void dfs(TreeNode root, List> result, int depth) {
        if (root == null) return;
        if (result.size() < depth + 1) {
            result.add(0, new ArrayList<>());  //改为在队头插入新list
        }
        dfs(root.left, result, depth + 1);
        dfs(root.right, result, depth + 1);
        result.get(result.size() - 1 - depth).add(root.val); // 容易出bug, 这个size是当前所知的最大数高,depth是已知的只等于从队尾开始计数的list数目,从前数的index会变 
        // .add这行的位置可以往前在dfs前或者两dfs中间都可以    
    }
}
class Solution {  // bfs
    public List> levelOrderBottom(TreeNode root) {
        List> result = new LinkedList<>();
        Queue queue = new LinkedList<>();
        if (root != null) queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            result.add(0, new ArrayList<>());
            while (size-- > 0) {
                TreeNode cur = queue.poll();
                result.get(0).add(cur.val);
                if (cur.left != null) queue.offer(cur.left);
                if (cur.right != null) queue.offer(cur.right);
            }
        }
        return result;
    }
}

199 二叉树的右视图

https://leetcode.cn/problems/binary-tree-right-side-view/description/

可以BFS,当确认是当层最后一个节点时输出;这里用中右左的pre-order dfs,只有是前序遍历时,填结果的顺序才能保证是从上层到下层的顺序,因为后序遍历填出来是从下到上,中序遍历在depth上的顺序是乱的。

class Solution {
    public List rightSideView(TreeNode root) {
        List result = new ArrayList<>();
        dfs(root, result, 0);
        return result;
    }
    private void dfs(TreeNode root, List result, int depth) { //按中右左进行前序遍历
        if (root == null) return;
        if (result.size() < depth + 1) {
            result.add(root.val);
        }
        dfs(root.right, result, depth + 1);
        dfs(root.left, result, depth + 1);
    }
}

637 二叉树的层平均值

https://leetcode.cn/problems/average-of-levels-in-binary-tree/description/

BFS更直接。

class Solution {
    public List averageOfLevels(TreeNode root) {
        Queue queue = new ArrayDeque<>();
        List result = new ArrayList<>();
        if (root != null) queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            double sum = 0.0;
            for (int i = 0; i < size; i++) {
                TreeNode cur = queue.poll();
                sum += cur.val;
                if (cur.left != null) queue.offer(cur.left);
                if (cur.right != null) queue.offer(cur.right);
            }
            result.add(sum / size);
        }
        return result;
    }
}

429 N叉树的层序遍历

https://leetcode.cn/problems/n-ary-tree-level-order-traversal/description/

BFS比较方便,DFS也可以做,和102题一样。

class Solution {
    public List> levelOrder(Node root) {
        List> result = new ArrayList<>();
        Queue queue = new ArrayDeque<>();
        if (root != null) queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            result.add(new ArrayList<>());
            while (size-- > 0) {
                Node cur = queue.poll();
                result.get(result.size() - 1).add(cur.val);
                for (Node child : cur.children) {
                    queue.offer(child);
                }
            }
        }
        return result;
    }
}

515 在每个树行中找最大值

https://leetcode.cn/problems/find-largest-value-in-each-tree-row/ BFS更直观,这里写DFS,DFS里更新最大可前中后序,但是在line 9在list里加入该层第一个点作为place holder需要在前序中,否则会out of bound.

class Solution {
    public List largestValues(TreeNode root) {
        List result = new ArrayList<>();
        dfs(root, result, 0);
        return result;
    }
    private void dfs(TreeNode root, List result, int depth) {
        if (root == null) return;
        if (result.size() < depth + 1) result.add(root.val); //bug 一定要先把空开出来,不然dfs在前会out of bound
        dfs(root.left, result, depth + 1);
        if (root.val > result.get(depth)) result.set(depth, root.val);  //可以在第一个dfs前也可以在第二个dfs后
        dfs(root.right, result, depth + 1);
    }
}

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

https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/

如果不是该层第一个,则让pre.next指向它。这题DFS不方便。

class Solution {
    public Node connect(Node root) {
        if (root == null) return root;
        Queue queue = new ArrayDeque<>();
        Node pre = root;
        queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                Node cur = queue.poll();
                if (i != 0) pre.next = cur;
                if (cur.left != null) queue.offer(cur.left);
                if (cur.right != null) queue.offer(cur.right);
                pre = cur;
            }
        }
        return root;
    }
}

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

https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/description/

和116完全一样,116是complet tree这里是general tree.

104 二叉树的最大深度

https://leetcode.cn/problems/maximum-depth-of-binary-tree/

可以BFS记录一个depth每层++,这里用DFS后序遍历。

class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) return 0;
        return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
    }
}

111 二叉树的最小深度

https://leetcode.cn/problems/minimum-depth-of-binary-tree/description/

BFS做法,遇到第一个叶子返回depth.

class Solution {      
    public int minDepth(TreeNode root) {
        Queue queue = new ArrayDeque<>();
        int depth = 0;
        if (root != null) queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            depth++;
            while (size-- > 0) {
                TreeNode cur = queue.poll();
                if (cur.left == null && cur.right == null) return depth;
                if (cur.left != null) queue.offer(cur.left);
                if (cur.right != null) queue.offer(cur.right);
            }
        }
        return depth;
    }
}

DFS 不能直接写

{ if (root == null) return 0;

return Math.min(minLeft, minRight) + 1; }

同时为null时0都有效,其他时候为0时无效忽略改为MAX。

class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) return 0;
        int minLeft = minDepth(root.left);
        int minRight = minDepth(root.right);
        if (minLeft == 0 && minRight != 0) minLeft = Integer.MAX_VALUE; 
        if (minRight == 0 && minLeft != 0) minRight = Integer.MAX_VALUE;
        return Math.min(minLeft, minRight) + 1;
    }
}

226 翻转二叉树

https://leetcode.cn/problems/invert-binary-tree/

BFS可以先翻孩子再把孩子入队可以,孩子入队再翻孩子也可以,DFS里前序和后序都可以, 中序也可以但第二个孩子要翻原来的右孩子,也就是新左孩子;卡哥也用了用栈的iterative的遍历方法这里没写。

class Solution {  // BFS
    public TreeNode invertTree(TreeNode root) {
        Queue queue = new ArrayDeque<>();
        if (root != null) queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            TreeNode temp = cur.left;
            cur.left = cur.right;
            cur.right = temp;      
            if (cur.left != null) queue.offer(cur.left);
            if (cur.right != null) queue.offer(cur.right);
        }
        return root;
    }
}
class Solution {  // DFS前序
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return root;
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }
}
class Solution {   // DFS后序
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return root;
        invertTree(root.left);
        invertTree(root.right);
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        return root;
    }
}
class Solution {   // DFS中序第二个孩子要翻原来的右孩子,也就是新左孩子
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return root;
        invertTree(root.left);
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        invertTree(root.left);
        return root;
    }
}

101 对称二叉树

https://leetcode.cn/problems/symmetric-tree/

做过的题又卡住了,卡住的原因在不知道如何两边同步一个从左遍历一个从右遍历,其实需要一个输入两个node的helper函数来实现。也可以两次遍历存下来再对比,但就需要n的space了。

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

你可能感兴趣的:(代码随想录,算法,数据结构,leetcode)