算法训练营Day14

#Java #二叉树层次遍历 #反转二叉树

开源学习资料

二叉树的层次遍历:力扣题目链接

二叉树的层次遍历很好理解:

就是从根结点一层一层地往下遍历(同一层,从左到右):

迭代的方式很好理解:就是依次入队出队。

但是判断条件怎么写?

最需要解决的就是,要把节点依次入队,那要怎么记录这些节点,防止它们丢失。

第一步把根节点先入队,这时候要想让它的左孩子和右孩子入队(如上图),就要在A出队的时候,记录它。

关键的就是在一个节点出队的时候,记录该节点,就能找到它的左右孩子。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> levelOrder(TreeNode root) {
        if(root == null){
            return res;
        }
    //模拟成一个队列
    //从根节点开始,依次入队(从左到右)
    Queue<TreeNode> queue = new LinkedList<>(); //创建一个队列
  
    //根节点先入队
    queue.offer(root);
    while(!queue.isEmpty()){
        int len = queue.size();
          List<Integer> list  = new ArrayList<>();
        while(len>0){
        //记录出队的节点
        TreeNode node = queue.poll();
        list.add(node.val);
        if(node.left!=null){
            //左孩子入队
            queue.offer(node.left);
        }
        if(node.right!=null){
            //右孩子入队
            queue.offer(node.right);
        }
        len--;
    }
    res.add(list);
    }
    return res;
    }
}

用两个while循环,主要是为了满足结果形式,保证每个结果都保存在一个新的集合中。

不然就是这样的(结果不能反映出是层次遍历)

先使用DFS迭代遍历练习以下题目:

二叉树的层序遍历II:力扣题目链接

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
 class Solution {
     List<List<Integer>> res = new LinkedList<>();
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
       Queue<TreeNode> que = new LinkedList<>();
       if(root == null){
           return res;
       }
       //先把根节点入队
       que.offer(root);
       while(!que.isEmpty()){
           List<Integer> list = new ArrayList<>();
           int size = que.size();
           //每一层入队出队
           for(int i =0;i<size;i++){
               TreeNode node = que.poll();
               list.add(node.val);
               if(node.left != null){
                   que.offer(node.left);
               }
               if(node.right != null){
                   que.offer(node.right);
               }
           }
           res.add(0,list);
       }
       return res;
        
    }
}

思路相同,只是用了链表的翻转。

二叉树的右视图:力扣题目链接

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Deque<TreeNode> que = new LinkedList<>();

        if (root == null) {
            return list;
        }

        que.offer(root);
        while (!que.isEmpty()) {
            int levelSize = que.size();

            for (int i = 0; i < levelSize; i++) {
                TreeNode node = que.poll();

                if (node.left != null) {
                    que.offer(node.left);
                }
                if (node.right != null) {
                    que.offer(node.right);
                }
                //就多一步:
                //只要最右边的:
                if (i == levelSize - 1) {
                    list.add(node.val);
                }
            }
        }

        return list;
    }
}

 这道题就关键的一步:只把最右边的放到结果中!

二叉树的层平均值:力扣题目链接

给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。 

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> list = new ArrayList<>();
    Queue<TreeNode> que = new LinkedList<>();
    if(root==null){
        return list;
    }
    que.offer(root);
    while(!que.isEmpty()){
        int size = que.size();
        Double sum =0.0;
        for(int i =0 ;i<size;i++){
            TreeNode node = que.poll();
            sum+=node.val;
            if(node.left!=null){
                que.offer(node.left);
            }
            if(node.right!=null){
                que.offer(node.right);
            }
        }
        Double average = sum/size;
        list.add(average);
    }
    return list;
    }
}

一层一层计算 !

 N叉树的层序遍历:力扣题目链接

给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。 

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        if (root == null) {
            return new ArrayList<List<Integer>>();
        }

        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        Queue<Node> queue = new ArrayDeque<Node>();
        queue.offer(root);

        while (!queue.isEmpty()) {
            int cnt = queue.size();
            List<Integer> level = new ArrayList<Integer>();
            for (int i = 0; i < cnt; ++i) {
                Node cur = queue.poll();
                level.add(cur.val);
                for (Node child : cur.children) {
                    queue.offer(child);
                }
            }
            ans.add(level);
        }

        return ans;
    }
}

在每个树行中找最大值:力扣题目链接

您需要在二叉树的每一行中找到最大的值。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    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;
    }
}

二叉树的最大深度:力扣题目链接

给定一个二叉树 root ,返回其最大深度。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

class Solution {
    public int maxDepth(TreeNode root) {
      if (root == null)   return 0;
   //先创建一个队列
    Queue<TreeNode> que = new LinkedList<>();
    //利用层次遍历
    //加入节点
    que.offer(root);
    int deep =0;
    while(!que.isEmpty()){
        int len = que.size();
        while(len>0){
         TreeNode node = que.poll();
         if(node.left!=null) que.offer(node.left);
         if(node.right!=null) que.offer(node.right);
         len--;
        }
         deep++;
    }
      return deep;
    }
}

二叉树的最小深度 :力扣题目链接

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {
    Queue<TreeNode> que = new LinkedList<>();
    if(root == null){
        return 0;
    }
    que.offer(root);
    int deep=0;
    while(!que.isEmpty()){
        int size = que.size();
        deep++;
        for(int i =0;i<size;i++){
            TreeNode node = que.poll();
            if(node.left==null && node.right==null){
                return deep;
            }
            if(node.left!=null){
                que.offer(node.left);
            }
            if(node.right!=null){
                que.offer(node.right);
            }
        }
    }
    return deep;
    }
}

利用层序遍历快速刷完了这几道题,发现基本都是一个模板,只是根据每一个题的要求作出一些改变,大体上还是一模一样的。

体会:在外层while中执行的就是当前位置要做的事情,而内层的for循环/while循环,就为下一层做好准备,而size则是控制每层中的节点。

翻转二叉树:力扣题目链接

翻转一棵二叉树。

力扣示例:

这道题用递归来写:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
    //利用递归
    //递归出口:
    if(root == null){
        return null;
    }
    invertTree(root.left);
    invertTree(root.right);
    swap(root);
    return root;
    }

    //交换的方法
    public void swap(TreeNode root){
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
    }
}

代码很简单,但是要深刻理解递归!

1.递归的出口

2.方法的返回值

当 root 为 null 时,递归的出口就是返回 null。这是因为在二叉树的递归操作中,每个递归步骤都涉及到对左右子树的处理,而 null 表示一个空节点或者叶子节点的空子树。

在这个具体的情境中,当 invertTree 方法递归到叶子节点的左右子树时,这些子树是空的,因此将它们反转后仍然为空。返回 null 可以告诉上一级递归调用,这个空节点的左右子树已经反转完成。

return root, 是为了在递归结束后返回整个树反转后的根节点。

再来练习一道:


 对称二叉树:力扣题目链接

给定一个二叉树,检查它是否是镜像对称的。 

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
    if(root == null){
        return true;
    }
    return dfs(root.left,root.right);
    }

    boolean dfs(TreeNode left , TreeNode right){
        //递归结束条件:
        //左右子树都为空
        if(left == null && right ==null){
            return true;
        }
        //左右节点有一个为空
        if(left == null || right == null){
            return false;
        }
         //左右节点的值不相等
        if(left.val != right.val){
            return false;
        }
        return dfs(left.left,right.right) && dfs(left.right,right.left);
    }
}

这些都是比较简单的递归,思想主要是抓住:

方法的返回值

递归的终止条件

确定递归的单层逻辑

在代码随想录中有对这三部曲的详细概括!即时Review~~~~

我自光芒万丈,

何须他人半点光!

Fighting!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/248855.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Netty常见的设计模式

简介 设计模式在软件开发中起着至关重要的作用&#xff0c;它们是解决常见问题的经过验证的解决方案。而Netty作为一个优秀的网络应用程序框架&#xff0c;同样也采用了许多设计模式来提供高性能和可扩展性。在本文中&#xff0c;我们将探讨Netty中使用的一些关键设计模式&…

TS系列-keyof的妙用

案例1 1、如果&#xff0c;有一个接口&#xff0c;某个变量的类型&#xff0c;是这个接口的 key &#xff1f; keyof 后面可以跟 一个对象类型或者一个接口类型keyof 是把后面 对象或者接口 的 键 都提取出来&#xff0c;组成一个联合类型 interface IStudentAttr {name: stri…

【LeetCode刷题笔记(6-1)】【Python】【三数之和】【哈希表】【中等】

文章目录 三数之和题目描述示例示例1示例2示例3 提示解决方案1&#xff1a;【三层遍历查找】解决方案2&#xff1a;【哈希表】【两层遍历】 结束语 三数之和 三数之和 题目描述 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! …

nodejs微信小程序+python+PHP血液中心管理平台的设计与实现-计算机毕业设计推荐

在二十一世纪的今天&#xff0c;我国献血总量已经不容小觑&#xff0c;在全国人民的不懈努力下&#xff0c;贫血、缺血的病人已经有了足够的血液保障。与此同时&#xff0c;采血工作和血液入库、出库等工作也日愈繁重。为进一步提高采血工作和血液中心的工作效率&#xff0c;开…

【算法与数据结构】376、LeetCode摆动序列

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题难点在于要考虑到不同序列的情况&#xff0c;具体来说要考虑一下几种特殊情况&#xff1a; 1、上…

提前预警,时刻守护:迅软DLP的数据安全先锋

许多数据泄密事件的发生&#xff0c;往往都是由于没有在案发事前做好安全保护&#xff0c;使得重要信息被随意攻击、盗取、泄密。比起在危机发生后亡羊补牢&#xff0c;更重要的是应该在案发之前未雨绸缪。迅软DLP作为迅软股份研发的“重磅选手”&#xff0c;可为政企单位在一切…

物联网智能仓库解决方案

物联网智能仓库解决方案是一种基于物联网技术的仓库管理系统&#xff0c;通过自动化设备、智能化管理系统和大数据分析等技术&#xff0c;实现仓库的智能化运营和管理。 物联网智能仓库解决方案包括&#xff1a; 仓库设备自动化&#xff1a;通过自动化设备和技术&#xff0c;实…

OpenHarmony关于修改系统横屏导致启动视频显示不全问题解决

前言 OpenHarmony源码版本&#xff1a;4.0release 开发板&#xff1a;DAYU / rk3568 前段时间写的设置OpenHarmony启动视频&#xff0c;在竖屏状态下是正常的&#xff0c;但是横屏状态下显示不全。 链接直达&#xff1a;OpenHarmony 设备启动Logo和启动视频替换指南-CSDN博…

docker小白第四天

docker小白第一天 什么是镜像 1、是一种轻量级、可执行的独立软件包&#xff0c;它包含运行某个软件所需的所有内容&#xff0c;我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等)&#xff0c;这个打包好的运行环境就…

基于轻量级yolov5-seg全系列【n/s/m/l/x】参数模型开发构建工业场景下不同参数量级的滚珠丝杠传动表面缺陷分割检测系统

工业场景下的滚珠丝杠传动表面缺陷分割检测系统在我们前面的博文中已经有了相关的开发实践了&#xff0c;感兴趣的话可以自行阅读即可&#xff1a; 《助力工业生产质检&#xff0c;基于轻量级yolov5-seg开发构建工业场景下滚珠丝杠传动表面缺陷分割检测系统》 前文主要是以se…

【PS】修改 图片 文字

删除文字 1&#xff1a;框选要修改的文字 选择-色彩范围 调整色彩容差能看见字体的时候就OK&#xff08;记住用吸管吸取文字颜色&#xff09; 2&#xff1a;选择-修改-扩展-像素2 3&#xff1a;编辑-内容识别填充 现在文字去除了。 用污点画笔修复工具&#xff0c;对缺陷进行…

四十七、Redis分片集群

目录 一、分片集群结构 二、散列插槽 1、Redis如何判断某个key应该在哪个实例&#xff1f; 2、如何将同一类数据固定的保存在同一个Redis实例&#xff1f; 三、集群伸缩 四、故障转移 1、当集群中有一个master宕机时 &#xff08;1&#xff09;自动转移 &#xff08;2&…

[渗透测试学习] Codify - HackTheBox

首先nmap扫描端口 nmap -sV -sC -p- -v --min-rate 1000 10.10.11.239扫出来三个端口&#xff0c;22端口为ssh服务&#xff0c;80端口有http服务&#xff0c;3000端口为nodejs框架 尝试访问下80端口&#xff0c;发现页面重定向 将该域名添加到hosts里 sudo vim /etc/hosts 成…

MySQL数据库的基础概念

目录 顾名思义&#xff0c;数据库是用于存储数据的&#xff0c;那这些数据被存储在哪呢&#xff1f; 文件也能存储数据&#xff0c;那在这个基础上&#xff0c;为什么还要搞出一个数据库来存储数据呢&#xff1f; MySQL的客户端登录/退出指令、服务端的启动/关闭指令 数据…

mysql数据库损坏后重装,数据库备份

重装 先卸载 sudo apt-get remove --purge mysql-server mysql-client mysql-common sudo apt-get autoremove sudo apt-get autoclean 然后重新安装MySQL: sudo apt-get install mysql-server mysql-client 首先要先使用无密码登录数据库一定要使用 sudo mysql -uroo…

数据结构(七):树介绍及面试常考算法

一、树介绍 1、定义 树形结构是一种层级式的数据结构&#xff0c;由顶点&#xff08;节点&#xff09;和连接它们的边组成。 树类似于图&#xff0c;但区分树和图的重要特征是树中不存在环路。树有以下特点&#xff1a; &#xff08;1&#xff09;每个节点有零个或多个子节点…

企业微信旧版-新版网络连接错误,无法登录的解决方案

一.企业微微信无法登录故障 二.解决方案 1.网上的解决方案 **检查网络连接&#xff1a;**确保你的计算机正常连接到互联网。尝试打开其他网页&#xff0c;以确保网络连接正常。 **防火墙和安全软件&#xff1a;**某些防火墙或安全软件可能会阻止企业微信的正常连接。请确保你…

computed 和 watch 的奇妙世界:让数据驱动你的 Vue 应用(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

idea2023解决右键没有Servlet的问题

复制Servlet Class.java中的文件。 回到文件&#xff0c;然后点击小加号 然后输入刚刚复制的东西&#xff1a; 3. 此时右键有servlet。 4. 然后他让你输入下面两个框&#xff1a; JAVAEE TYPE中输入Servlet Class Name 表示你要创建的Servlet类的名称是什么。自己起名字。然后…

寒冷冬天,再次撕下了新能源汽车的续航遮羞布,北方真不适合

随着懂车帝的冬测&#xff0c;新能源汽车的冬天续航成为关注焦点&#xff0c;电池性能在冬天里缩减众所周知&#xff0c;不过从来没有机构告诉消费者&#xff0c;到底冬天电池的续航会减少多少&#xff0c;如今这一切显然暴露在人们眼前了。 懂车帝的冬测显示除了特别优秀的新能…