【代码训练营】day14 | 10.层序遍历 & 226.翻转二叉树 & 101.对称二叉树 2

70 阅读2分钟

所用代码 java

二叉树的层序遍历 LeetCode 102

题目链接: 二叉树的层序遍历 LeetCode 102 - 中等

思路

层序遍历(BFS)的话就是一个队列装每个结点,然后每次把结点遍历之后放入该结点的左右孩子

public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    if (root == null){
        return res;
    }
    Deque<TreeNode> deque = new ArrayDeque<>();
    deque.offer(root);
    while (!deque.isEmpty()){
        List<Integer> list = new ArrayList<>();
        // 由于后面size会一直变化,所有这么要先确定号size
        int size = deque.size();
        // 用for循环来遍历链表,并把每一层的所有值给放入list
        for (int i = 0; i < size; i++) {
            TreeNode node = deque.poll();
            list.add(node.val);
​
            // 每次存储结点之后还要把该结点的左右孩子加入队列
            if (node.left != null){
                deque.offer(node.left);
            }
            if (node.right != null){
                deque.offer(node.right);
            }
        }
        res.add(list);
    }
    return res;
}

还有一种递归的方式 DFS

public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    recurve(root,res,0);
    return res;
}
​
public void recurve(TreeNode node, List<List<Integer>> res, int deep){
    if (node == null) return;
    deep++;
   // System.out.println("打印一下该结点信息:" + node.val + "  deep = " + deep);
​
    if (res.size() < deep) {
        // 当层级增加时,item也增加
        List<Integer> item = new ArrayList<>();
        res.add(item);
    }
    // 根据所处的层级界定item的位置并加入
    res.get(deep - 1).add(node.val);
​
    recurve(node.left, res, deep);
    recurve(node.right, res, deep);
}

总结

层序遍历需要掌握bfs方法,注意每次需先确定好queue的长度,因为他每次搜索都是动态的工厂

翻转二叉树 LeetCode 226

题目链接:翻转二叉树 LeetCode 226 - 简单

思路

主要是进行递归遍历DFS,确定用哪种遍历顺序

递归三部曲:

  1. 确定返回值和参数 TreeNode;
  2. 确定终止条件 if (node == null) return node;
  3. 处理逻辑 swap(left, right);
public TreeNode invertTree(TreeNode root) {
    if (root == null){
        return root;
    }
    // 前序遍历 => 根左右
    swap(root);
    invertTree(root.left);
    invertTree(root.right);
    // 也可以把处理逻辑写到这里,就是后序遍历
    return root;
}
​
public void swap(TreeNode node){
    TreeNode temp = node.right;
    node.right = node.left;
    node.left = temp;
}

中序(不推荐):因为每次交换后,左子树到右子树去了,右子树交换到了左子树,再次递归同样也是左子树

层序遍历:

public TreeNode invertTree(TreeNode root) {
    if (root == null){
        return root;
    }
    Deque<TreeNode> deque = new ArrayDeque<>();
    deque.offer(root);
    while (!deque.isEmpty()){
        int size = deque.size();
        // 遍历每一层,并交换左右孩子结点
        for (int i = 0; i < size; i++) {
            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 node){
    TreeNode temp = node.right;
    node.right = node.left;
    node.left = temp;
}

对称二叉树 LeetCode 101

题目链接:对称二叉树 - LeetCode 101 - 简单

思路

无。


根结点的左子树是否可以和根结点的右子树相互翻转。

该题只能用后续遍历,因为我们要不断收集左右孩子的信息再返回给上一结点,才知道以左节点为根结点是数和以右节点为根结点的数是否可以相互翻转。因为只有后续遍历才能把底部孩子的信息返回给上一层!

    public boolean isSymmetric(TreeNode root) {
        if (root == null) return false;
​
        return compareLeftAndRight(root.left, root.right);
    }
​
    public boolean compareLeftAndRight(TreeNode left, TreeNode right){
        if (left == null && right == null) return true;
        else if (left == null && right != null) return false;
        else if (left != null && right == null) return false;
        else if (left.val != right.val) return false;
        // 不能加这一句,因为他会在当前结点就直接返回,没有进入叶子结点
//        else if (left.val == right.val) return true;
​
        // 比较外侧是否相等
        boolean outside = compareLeftAndRight(left.left, right.right);
        // 比较内侧是否相等
        boolean inside = compareLeftAndRight(left.right, right.left);
        // 查看两侧传递的布尔值是否相等
        boolean isSame = outside && inside;
​
        return isSame;
​
    }

总结

本题主要是同时处理两个二叉树的遍历过程,并且同时比较两个二叉树里面对应结点的情况。

左子树遍历顺序:左 右 中

右子树遍历顺序:右 左 中