自学内容网 自学内容网

刷算法Leetcode---8(二叉树篇)(层序遍历)

前言

        本文是跟着代码随想录的栈与队列顺序进行刷题并编写的 代码随想录

        二叉树的题目较多,就多分了几次写,这是第二篇

        第一篇二叉树的文章链接:刷算法Leetcode---7(二叉树篇)(前中后序遍历)

        这是力扣刷算法的其他文章链接:刷算法Leetcode文章汇总

二叉树篇(层序遍历)

(1)102. 二叉树的层序遍历 

        ①bfs+队列,每层队列大小代表该层总节点数,每次取出一层的节点取值并加入左右孩子

        ②dfs,根节点从第0层开始,递归每个节点的左右孩子和层数,将层数作为下标加入结果。层数大于res的大小时,代表该层是第一次遍历到,要new ArrayList<>()加入res中

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

(2)107. 二叉树的层序遍历 II

        ①bfs+队列,同102题,可直接将结果翻转,或者将每层结果level逆序加入res即可,res.add(0,level)

        ②dfs,同102题,可直接将结果翻转,或者遇到新层时头插res,层数作为逆序下标

(3)199. 二叉树的右视图 

        ①bfs+队列,同102题,在获取每层节点时,只记录最后一个节点

        ②dfs,同102题,每次递归左右节点和层数,层数作为下标,若遇到同层节点就替换,否则直接添加

        ③dfs,大致同102题,但是先递归右节点再递归左节点,若遇到同层则忽略,否则直接添加

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

(4)637. 二叉树的层平均值

        ①bfs+队列,同102题,记录每层节点数和总和,将平均值加入结果

        ②dfs,同102题,使用sum和count两个ArrayList记录每层的总和与个数,注意sum进行add时要用1.0乘

class Solution {
    private List<Double> res;
    private List<Double> sum;
    private List<Integer> count;
    public List<Double> averageOfLevels(TreeNode root) {
        res = new ArrayList<>();
        sum = new ArrayList<>();
        count = new ArrayList<>();
        dfs(root,0);
        for(int i=0;i<sum.size();i++){
            res.add(sum.get(i)/count.get(i));
        }
        return res;
    }
    private void dfs(TreeNode node,int depth){
        if(node==null)return;
        if(depth<sum.size()){
            sum.set(depth,sum.get(depth)+node.val);
            count.set(depth,count.get(depth)+1);
        }
        else{
            sum.add(1.0*node.val);
            count.add(1);
        }
        dfs(node.left,depth+1);
        dfs(node.right,depth+1);
    }
}

(5)429. N 叉树的层序遍历

        bfs+队列,同102题,但不是添加左右孩子,而是遍历添加所有的孩子节点,可用增强for循环

class Solution {
    private List<List<Integer>> res;
    private List<Integer> level;
    private Deque<Node> queue;
    public List<List<Integer>> levelOrder(Node root) {
        res = new ArrayList<>();
        queue = new ArrayDeque<>();
        if(root==null)return res;
        queue.addLast(root);
        while(!queue.isEmpty()){
            int num = queue.size();
            level = new ArrayList<>();
            for(int i=0;i<num;i++){
                Node temp = queue.pollFirst();
                level.add(temp.val);
                for(Node child:temp.children){
                    queue.addLast(child);
                }
            }
            res.add(level);
        }
        return res;
    }
}

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

        ①bfs+队列,同102题,遍历每层节点时记录最大值

        ②dfs,同102题,遇到同层取更大值

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

        ①bfs+队列,同102题,遍历每层除最后一个节点外,next指针指向队头节点,即同层下一个节点

        ②dfs,同102题,遇到同层先将next指针指向新节点,再记录新节点

        ③bfs+next指针迭代,使用两个指针node1和node2实现,node1记录下一层最左节点用于标记下一层,node2遍历当前层,实现每个节点左右子节点的next连接,以及node2右节点和node2的next节点的左节点next连接。利用已有节点的next指针实现对一个层的遍历

class Solution {
    public Node connect(Node root) {
        if(root==null)return root;
        Node node1=root,node2=null;
        while(node1!=null&&node1.left!=null){
            node2=node1;
            node1=node1.left;
            while(node2!=null){
                node2.left.next=node2.right;
                if(node2.next!=null)node2.right.next=node2.next.left;
                node2=node2.next;
            }    
        }
        return root;
    }
}

        ④bfs+next指针递归,同上一种方法,使用递归实现

class Solution {
    public Node connect(Node root) {
        if(root==null)return root;
        bfs(root);
        return root;
    }
    private void bfs(Node node){
        if(node==null||node.left==null)return;
        Node temp = node;
        while(temp!=null){
            temp.left.next=temp.right;
            if(temp.next!=null)temp.right.next=temp.next.left;
            temp=temp.next;
        }
        bfs(node.left);
    }
}

        ⑤dfs,对每个节点,只用连接左右子节点和next的子节点即可,再递归左右子节点完成整颗树的连接

class Solution {
    public Node connect(Node root) {
        if(root==null||root.left==null)return root;
        root.left.next=root.right;
        root.right.next=root.next!=null?root.next.left:null;
        connect(root.left);
        connect(root.right);
        return root;
    }
}

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

        ①bfs+队列,同116题方法一

        ②dfs,同116题方法二

        ③bfs+next指针迭代,使用nextLeftNode、currNode、preNode三个指针,nextLeftNode为下一层虚拟头节点标识下一层,currNode遍历当前层,preNode为下一层已遍历的最右边节点(便于下一层next指针连接)。遍历一层时,对于每个节点的左右子节点,进行preNode的next指针连接并更新。使用nextLeftNode虚拟头节点便于判断是否还有下一层并初始化preNode

class Solution {
    public Node connect(Node root) {
        if (root == null) return null;
        Node nextLeftNode = null, currNode = root, preNode = null;
        while (currNode!=null) { // 每层
            nextLeftNode = new Node(0); // 下一层的虚拟头节点
            preNode = nextLeftNode;
            while (currNode != null) { // 遍历当前层
                if(currNode.left!=null){
                    preNode.next=currNode.left;
                    preNode=preNode.next;
                }
                if(currNode.right!=null){
                    preNode.next=currNode.right;
                    preNode=preNode.next;
                }
                currNode = currNode.next;
            }
            currNode=nextLeftNode.next;
        }
        return root;
    }
}

(9)104. 二叉树的最大深度

        ①bfs+队列,同102题,每遍历一层记录一次

        ②dfs,递归左右节点,取层数更大的

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

(10)111. 二叉树的最小深度

        ①bfs,同102题,遇到叶子节点就返回层数

class Solution {
    private Deque<TreeNode> queue;
    private int res;
    public int minDepth(TreeNode root) {
        if(root==null)return 0;
        queue = new ArrayDeque<>();
        queue.addLast(root);
        while(!queue.isEmpty()){
            int num = queue.size();
            res+=1;
            for(int i=0;i<num;i++){
                TreeNode temp = queue.pollFirst();
                if(temp.left==null&&temp.right==null)return res;
                if(temp.left!=null)queue.addLast(temp.left);
                if(temp.right!=null)queue.addLast(temp.right);
            }
        }
        return res;
    }
}

        ②dfs递归,若左右都不为零,则取最小加一,否则(即左右至少空一个)取不为零加一

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

二叉树篇(层序遍历)总结

        ①bfs+队列,可通过队列大小获取每层节点数

        ②dfs,递归每个节点的层数进行记录,根据题目需要设定根节点的层数为0还是1

        ③对于116和117题,可使用next指针进行一层遍历,同时要记录下一层位置和next连接节点


原文地址:https://blog.csdn.net/m0_70220973/article/details/140097850

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!