DAY15 | 层序遍历合集 / 226.翻转二叉树 / 101.对称二叉树

本文探讨了二叉树和N叉树的层序遍历算法,包括基本实现、反转、右视图、层平均值计算,以及N叉树的特例。还涉及填充节点指针、最大深度、最小深度和特殊操作如翻转和对称判断。深入理解了递归与迭代方法在这些问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

层序遍历

在这里插入图片描述

102.二叉树的层序遍历

用队列实现。

List<List<Integer>> res = new ArrayList<List<Integer>>();
    
public List<List<Integer>> levelOrder(TreeNode root) {
    if(root == null) return res;
    Queue<TreeNode> q = new LinkedList<>();
    q.offer(root);

    while(!q.isEmpty()){
        int size = q.size();
        List<Integer> innerRes = new ArrayList<>();
        while(size > 0){
            TreeNode t = q.poll();
            innerRes.add(t.val);
            size--;
            if(t.left!=null){
                q.offer(t.left);
            }
            if(t.right!=null){
                q.offer(t.right);
            }
        }
        res.add(innerRes);

    }
    return res;
}
107.二叉树的层序遍历II

在上道题的基础上反转res数组。

public List<List<Integer>> levelOrderBottom(TreeNode root) {
    List<List<Integer>> res = new ArrayList<List<Integer>>();


    if(root == null) return res;
    Queue<TreeNode> q = new LinkedList<>();
    q.offer(root);

    while(!q.isEmpty()){
        int size = q.size();
        List<Integer> innerRes = new ArrayList<>();
        while(size > 0){
            TreeNode t = q.poll();
            innerRes.add(t.val);
            size--;
            if(t.left!=null){
                q.offer(t.left);
            }
            if(t.right!=null){
                q.offer(t.right);
            }
        }
        res.add(innerRes);

    }
    Collections.reverse(res);
    return res;
}
199.二叉树的右视图

用size的值判断是不是每一层最后一个结点。

public List<Integer> rightSideView(TreeNode root) {
    Queue<TreeNode> q = new LinkedList<>();
    List<Integer> res = new ArrayList<>();
    if(root == null){
        return res;
    }
    q.offer(root);
    while(!q.isEmpty()){
        int size = q.size();
        while(size > 0){
            TreeNode t = q.poll();
            
            // 核心部分
            if(--size == 0){
                res.add(t.val);
            }
            
            if(t.left!=null){
                q.offer(t.left);
            }
            if(t.right != null){
                q.offer(t.right);
            }
        }
    }
    return res;
}
637.二叉树的层平均值

每层取平均值。

public List<Double> averageOfLevels(TreeNode root) {
    List<Double> res = new ArrayList<>();
    if(root == null){
        return res;
    }
    Queue<TreeNode> q = new LinkedList<>();
    q.offer(root);
    while(!q.isEmpty()){
        Double sum = 0.0;
        int size = q.size();
        for(int i = 0; i < size; i++){
            TreeNode t = q.poll();

            // 核心部分
            sum += 1.0 * t.val;

            if(t.left != null){
                q.offer(t.left);
            }
            if(t.right != null){
                q.offer(t.right);
            }
        }
        res.add(sum / size);
    }
    return res;
}
429.N叉树的层序遍历

和二叉树本质上没什么区别。

public List<List<Integer>> levelOrder(Node root) {
    List<List<Integer>> res = new ArrayList<List<Integer>>();
    if(root == null){
        return res;
    }
    Queue<Node> q = new LinkedList<>();
    q.offer(root);
    while(!q.isEmpty()){
        int size = q.size();
        List<Integer> innerRes = new ArrayList<>();
        while(size-- > 0){
            Node n = q.poll();
            innerRes.add(n.val);
            List<Node> children = n.children;
            
            // 最好加上这句
            if (children == null || children.size() == 0) {
                    continue;
                }
            
            for(Node child : children){
                if(child!=null){
                    q.offer(child);
                }
            }
        }
        res.add(innerRes);
    }
    return res;
}
515.在每个树行中找最大值
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.填充每个节点的下一个右侧节点指针
public Node connect(Node root) {
    if(root == null) return root;
    Queue<Node> que = new LinkedList<>();
    que.offer(root);
    while(!que.isEmpty()){
        int size = que.size();
        Node p = null;
        Node q = null;
        if(size > 0){
            p = que.poll();
        }
        while(size > 0){
            if(size > 1){
                q = que.poll();
            }else{
                q = null;
            }
            size--;
            p.next = q;

            if(p.left!=null){
                que.offer(p.left);
            }
            if(p.right!=null){
                que.offer(p.right);
            }

            p = q;
        }

    }
    return root;
}
117.填充每个节点的下一个右侧节点指针

和上道题代码一样。

104.二叉树的最大深度
方法一:迭代(层序遍历)
public int maxDepth(TreeNode root) {
    if(root == null) return 0;
    int depth = 0;
    Queue<TreeNode> que = new LinkedList<>();
    que.offer(root);
    while(!que.isEmpty()){
        depth++;
        int size = que.size();
        while(size-- > 0){
            TreeNode t = que.poll();
            if(t.left!=null){
                que.offer(t.left);
            }
            if(t.right!=null){
                que.offer(t.right);
            }
        }
    }
    return depth;
}
方法二:递归

DAY16再讲。

// 方法二:递归
public int maxDepth(TreeNode root) {
    if(root == null) return 0;
    return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
111.二叉树的最小深度
方法一:迭代(层序遍历)
public int minDepth(TreeNode root) {
    if(root == null) return 0;
    int depth = 0;
    Queue<TreeNode> que = new LinkedList<>();
    que.offer(root);
    
    // 只要有结点没孩子,就到此为止计算深度
    boolean hasChild = true;
    
    while(!que.isEmpty() && hasChild){
        hasChild = true;
        depth++;
        int size = que.size();
        while(size-- > 0){
            TreeNode t = que.poll();
            
            // 核心部分
            if(t.left!=null){
                que.offer(t.left);
            }
            if(t.right!=null){
                que.offer(t.right);
            }
            if(t.left==null && t.right==null){
                hasChild = false;
                break;
            }
            
        }
    }
    return depth;
}
方法二:递归

DAY16再讲。


226.翻转二叉树

  • 标签:二叉树、递归、迭代
  • 难度:5.5

只是在二叉树的前序遍历代码上做了点处理。

// 方法一:递归
public TreeNode invertTree(TreeNode root) {
    if(root == null){
        return null;
    }
    
    //处理如下
    swapChildren(root);
    
    invertTree(root.left);
    invertTree(root.right);
    return root;
}

// 方法二:迭代
public TreeNode invertTree(TreeNode root){
    if(root == null) return null;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while(!stack.isEmpty()){
        TreeNode t = stack.pop();
        
        //处理如下
        swapChildren(t);
        
        if(t.right!=null){
            stack.push(t.right);
        }
        if(t.left!=null){
            stack.push(t.left);
        }
    }
    return root;
}

public void swapChildren(TreeNode node){
    TreeNode temp = node.left;
    node.left = node.right;
    node.right = temp;
}

101.对称二叉树

  • 标签:二叉树、递归、迭代
  • 难度:6.0
方法一:递归

递归做法,就是先排除左右有一个空,或左右值不相等的情况,再用后序遍历进行比较。

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;
}
方法二:迭代

迭代使用双端队列,同时在两端插入左右元素,进行比较。

/**
 * 迭代法
 * 使用双端队列,相当于两个栈
 */
public boolean isSymmetric2(TreeNode root) {
    Deque<TreeNode> deque = new LinkedList<>();
    deque.offerFirst(root.left);
    deque.offerLast(root.right);
    while (!deque.isEmpty()) {
        TreeNode leftNode = deque.pollFirst();
        TreeNode rightNode = deque.pollLast();
        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.offerFirst(leftNode.left);
        deque.offerFirst(leftNode.right);
        deque.offerLast(rightNode.right);
        deque.offerLast(rightNode.left);
    }
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值