【二叉树练习2】

文章目录

  • 判断是否是完全二叉树
  • 找出p和q的最近的公共祖先
  • 非递归实现前序遍历
  • 非递归实现中序遍历
  • 非递归实现后序遍历


判断是否是完全二叉树

    boolean isCompleteTree(TreeNode root){
        if (root == null){
            return true;
        }
        //创建队列
        Queue<TreeNode> queue = new LinkedList<>();
        //把根放进队列里
        queue.offer(root);
        while (!queue.isEmpty()){
        //把出队列的放进cur里
            TreeNode cur = queue.poll();
            //当cur不等于空时,把cur的左子树和右子树放进队列
            if (cur != null){
                queue.offer(cur.left);
                queue.offer(cur.right);
            }else{
            //如果cur放进了null,说明要跳出队列进入判断环节
                break;
            }
        }
        while(!queue.isEmpty()){
            TreeNode tmp = queue.peek();//瞄一眼队列的数
            if (tmp == null){
                queue.poll();
            }else{
            //遇到不为空的说明不是完全二叉树
                return false;
            }
        }
        //来到这里说明tmp全部是空的,是完全二叉树
        return true;

    }

找出p和q的最近的公共祖先

1.root节点是p或q其中的一个,那么root就是最近的公共祖先
在这里插入图片描述
2.p和q分别在root的两侧,那么root是最近的公共祖先
在这里插入图片描述
3.p和q在root的同一侧
在这里插入图片描述
原理:root还是在遍历这棵树,遇到p或q就返回。


    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {

        if (root == null) return null;
        if (root == p || root == q) {
            return root;
        }
        TreeNode leftTree = lowestCommonAncestor(root.left, p, q);
        TreeNode rightTree = lowestCommonAncestor(root.left, p, q);
        if (leftTree != null && rightTree != null) {
            return root;
        } else if (leftTree != null) {
            return leftTree;

        } else {
            return rightTree;
        }
    }

还有第二种方法
大概意思就是:找p那条路径,和q那条路径出现的节点,然后放进两个栈里,保证两个栈的数相同,多的去掉,然后栈中相同的元素就是他们最近的公共祖先。
在这里插入图片描述

public class BinaryTree {
    static class TreeNode{
        public char val;
        public  TreeNode left;
        public  TreeNode right;

        public TreeNode(char val) {
            this.val = val;
        }
    }
    public TreeNode creatTree(){
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');
        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        C.left = F;
        C.right = G;
        E.right = H;

        return A;
    }

    public TreeNode lowestCommonAncestor2(TreeNode root,TreeNode p,TreeNode q){
        if(root == null) return null;
        //创建两个栈
        Stack<TreeNode> stackP = new Stack<>();
        Stack<TreeNode> stackQ = new Stack<>();
        //两条路径
        getPath(root,p,stackP);
        getPath(root,q,stackQ);
        //大小
        int sizeP = stackP.size();
        int sizeQ = stackP.size();
        if (sizeP > sizeQ){
            int size = sizeP - sizeQ;
            while (size != 0){
                stackP.pop();
                size--;
            }
        }else {
            int size = sizeQ - sizeP;
            while (size != 0){
                stackQ.pop();
                size--;
            }
        }
        //两个栈元素一样多
        while(!stackP.isEmpty() && !stackQ.isEmpty()){
            if (stackP.peek() == stackQ.peek()){
                return stackP.peek() ;
            }else{
                stackP.pop();
                stackQ.pop();
            }
        }
        return null;

    }

    private boolean getPath(TreeNode root, TreeNode node, Stack<TreeNode> stack){
        if (root == null || node == null){
            return false;
        }
        stack.push(root);
        if (root == node){
            return true;
        }
        boolean flg1 = getPath(root.left, node, stack);
        if(flg1){
            return true;
        }
        boolean flg2 = getPath(root.right, node, stack);
        if(flg2){
            return true;
        }
        stack.pop();
        return false;

    }
}

非递归实现前序遍历

    //递归实现前序遍历
    void preOrder(TreeNode root){
        //根左右
        if(root == null){
            return;
        }
        System.out.print(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);

    }
//非递归实现前序遍历
    void preOrderNor(TreeNode root) {
        if (root == null) {
            return;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;

        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                System.out.print(cur.val + " ");
                cur = cur.left;
            }

            TreeNode top = stack.pop();
            cur = top.right;
            //1.为空,返回;不为空创建栈,让cur=root;
            //当cur!=null时,把cur放进栈里,并打印cur.val;再让cur=root.left。
            //当cur==null时,让top=栈顶元素,然后让cur=top.right
        }
    }

非递归实现中序遍历

    //中序遍历
    void inOrder(TreeNode root){
        //左根右
        if(root == null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);

    }
    //非递归中序遍历
    void inorderNor(TreeNode root){
        if (root == null){
            return;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while(cur != null || !stack.isEmpty()){
            while(cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            System.out.print(top.val+" ");
            cur = top.right;
        }
        //不为空,创建栈,让cur=root,把cur放进栈里,然后遍历cur的左边。
        //直到cur遇到空,说明cur的左边遍历完了
        //让top=栈顶元素,并打印top的值,让cur=top.right。

    }

非递归实现后序遍历

    //后序遍历
    void postOrder(TreeNode root){
        //左右根
        if(root == null){
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }
    //非递归后序遍历
    void postOrderNor(TreeNode root){
        if (root == null){
            return;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        TreeNode prev = null;
        while(cur != null || !stack.isEmpty()){
            while(cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
        }
        TreeNode top = stack.peek();
        if (top.right == null || top.right == prev){
            System.out.print(top.val+" ");
            stack.pop();
            prev = top;
        }else{
            cur = top.right;
        }
        //先创建栈,让cur=root,cur不等于空或者栈不为空,当cur不等于空时,让cur入栈,然后让cur=cur.left,
        //直到当cur等于空时,定义prev=null;让top=瞄一眼栈顶元素,如果等于空或者top.right=prev进入循环,
        // 循环内打印top.val,并且出栈,然后让prev=top,否则让cur=cur.right
    }

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

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

相关文章

Midjourney在线绘画及提示词精选库

网址:https://chat.xutongbao.top/ 一碗面粉&#xff1a; Self-Rising Flour in a 50s colourful bowl. professional photograph --ar 720:1170 --v 6 烟花古建筑&#xff1a; At night, with the snow-covered scenery of the Beijing Forbidden City as the backdrop, brill…

linux内核源码编译2.6失败

centos7环境 iso选择 https://mirrors.tuna.tsinghua.edu.cn/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-2009.iso 自带qemu&#xff0c;未实测是否可用 选择编译版本2.6 下载地址 遇到的编译错误解决 yum list | grep curses yum install ncurses-devel.x86_64 -y yum i…

算法专题[递归-搜索-回溯-2-DFS]

算法专题[递归-搜索-回溯-2-DFS] 一.计算布尔二叉树的值&#xff1a;1.思路一&#xff1a;2.GIF题目解析 二.求根节点到叶子节点的数字之和1.思路一&#xff1a;2.GIF题目解析 三.二叉树剪枝1.思路一&#xff1a;2.GIF题目解析 四.验证二叉搜索树1.思路一&#xff1a;2.GIF题目…

触摸屏监控双速电动机-硬件设计1

主电路设计 主电路如图所示。三相总电源从前门配电箱的-X1-1接线端子排引出&#xff0c;给混料泵电动机供三相电&#xff0c;给PLC供单相电。混料泵电动机用KM3主触点接通低速&#xff0c;用KM4的主触点和辅助触点接通高速。注意&#xff0c;高低速切换时&#xff0c;双速电动…

18G大小的R包 | 将你需要的R包全部下载

写在前面 在上周&#xff0c;我们在社群讨论。安装R包是个玄学”有时候真的很奇怪&#xff0c;在自己的电脑上就是无法安装&#xff0c;但是在其他电脑都可以正常安装…&#xff0c;不是感到很无语&#xff1f;&#xff1f;&#xff1f;&#xff1f;没有办法&#xff0c;类似的…

数据结构之栈和队列

数据结构之栈和队列 1、栈1.1、栈的定义及基本运算1.2、栈的存储结构 2、队列2.1、队列的定义及基本运算2.2、队列的存储结构2.3、队列的应用 数据结构是程序设计的重要基础&#xff0c;它所讨论的内容和技术对从事软件项目的开发有重要作用。学习数据结构要达到的目标是学会从…

【计算机网络】【Python】【练习题】【新加坡南洋理工大学】【Computer Control Network】

一、题目描述 该题目描述一个网络中数据包交换&#xff08;Packet Switching&#xff09;的例子。题目如下&#xff1a; 二、问题解答&#xff08;使用Python&#xff09; Q1&#xff1a;如何求出0.0004这个值&#xff1f; &#xff08;1&#xff09;、公式推导过程&#xf…

4.servera修改主机名,配置网络,以及在cmd中远程登录servera的操作

1.先关闭这两节省资源 2.对于新主机修改主机名&#xff0c;配置网络 一、配置网络 1.推荐图形化界面nmtui 修改完成后测试 在redhat ping一下 在redhat远程登录severa 2、使用nmcli来修改网络配置 2.1、配置要求&#xff1a;主机名&#xff1a; node1.domain250.exam…

<信息安全>《1 国内主要企业网络安全公司概览(一)》

1 深信服科技股份有限公司 信息内容LOGO成立日期2000年12月25日成立。总部深圳市南山区学苑大道1001号南山智园A1栋是否上市深信服[300454]A股市值265亿主要产品企业级网络安全云计算IT基础设施数据通信物联网员工规模9000人分支机构全球50多个荣誉国家级高新技术企业、中国软…

JVM系列-3.类的生命周期

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理&#x1f525;如果感觉博主的文…

Kotlin协程的JVM实现源码分析(下)

协程 根据 是否保存切换 调用栈 &#xff0c;分为&#xff1a; 有栈协程&#xff08;stackful coroutine&#xff09;无栈协程&#xff08;stackless coroutine&#xff09; 在代码上的区别是&#xff1a;是否可在普通函数里调用&#xff0c;并暂停其执行。 Kotlin协程&…

NG+WAF实现应用安全访问

一、基本概念 什么是waf&#xff1f; Web应用防火墙&#xff08;waf&#xff09;是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品&#xff0c;WAF是一种工作在应用层的、通过特定的安全策略来专门为Web应用提供安全防护的产品。 什么是ngx_lua_…

2024年开年的荣誉--来自国产数据库

上周在北京参加了阿里云的开发者大会&#xff0c;我因为去年做了一点小贡献。非常荣幸的获得了阿里云的MVP的这个殊荣。&#xff08;期间也认识了一些大神级的人物&#xff09;还有就是一些网上认识的打卡们线下见面。 这个也是我一直追求的荣誉。 几乎在同时P&#xff08;Ping…

单机zk--数据恢复,处理客户端接入,两种超期机制,处理客户端请求,客户端主动断开

1.概述 zk是一个分布式内存数据库。既然是数据库&#xff0c;就需要处理客户端发送过来的读&#xff0c;写请求。随着请求执行&#xff0c;不断更改数据实体。 作为内存数据库&#xff0c;数据实体全部加载到内存&#xff0c;在内存修改。我们把客户端发来的请求叫做事务&…

SpringCloud之OpenFeign的学习、快速上手

1、什么是OpenFeign OpenFeign简化了Http的开发。在RestTemplate的基础上做了封装&#xff0c;在微服务中的服务调用发送网络请求起到了重要的作用&#xff0c;简化了开发&#xff0c;可以让我们跟写接口一样调其他服务。 并且OpenFeign内置了Ribbon实现负载均衡。 官方文档…

【RT-DETR有效改进】华为 | Ghostnetv1一种专为移动端设计的特征提取网络

前言 大家好&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持ResNet32、ResNet101和PP…

代码随想录二刷 | 回溯 | 组合优化

代码随想录二刷 &#xff5c; 回溯 &#xff5c; 组合优化 剪枝优化 剪枝优化 在遍历的过程中有如下代码&#xff1a; for (int i startIndex; i < n; i) {path.pop_back();backtracking(n, k, i 1);path.pop_back(); }n 4&#xff0c;k 4的话&#xff0c;那么第一层f…

SQL注入实战:盲注

盲注&#xff1a; 1、当攻击者利用SQL注入漏洞进行攻击时&#xff0c;有时候web应用程序会显示&#xff0c;后端数据库执行SQL查询返回的错误信息&#xff0c;这些信息能帮助进行SQL注入&#xff0c;但更多时候&#xff0c;数据库没有输出数据web页面&#xff0c;这是攻击者会…

flutter 实现定时滚动的公告栏的两种不错方式

相同的部分 自定义一个类继承StatefulWidget 所有公告信息存放在list里 第一种 scrollControllerAnimatedContainer 逻辑如下 我们可以发现启动了一个timer计时器计时5秒&#xff0c;hasClients检查其目标对象&#xff08;我们用的是listview&#xff09;是否被渲染&#x…