训练营day15

news2024/11/15 13:39:25
  • 层序遍历 10
  • 226.翻转二叉树
  • 101.对称二叉树 2

102.二叉树的层序遍历

力扣题目链接

 给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

 102.二叉树的层序遍历

 

接下来我们再来介绍二叉树的另一种遍历方式:层序遍历。

层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。

需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。

而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。

使用队列实现二叉树广度优先遍历,动画如下:

 

 

var levelOrder =function(root){
    if(!root) return []
    const queue = [root]
    const res = []
    while(queue.length){
        //level用来存储每一层的节点值
        const level = []
        const len = queue.length
        for(let i = 0; i < len; i++){
            const node = queue.shift()
            level.push(node.val)
            //queue用来存储下一层的节点
            if(node.left) queue.push(node.left)
            if(node.right) queue.push(node.right)
        }
        res.push(level)
    }
    return res
}
//代码随想录答案
var levelOrder = function(root) {
    //二叉树的层序遍历
    let res = [], queue = [];
    queue.push(root);
    if(root === null) {
        return res;
    }
    while(queue.length !== 0) {
        // 记录当前层级节点数
        let length = queue.length;
        //存放每一层的节点 
        let curLevel = [];
        for(let i = 0;i < length; i++) {
            let node = queue.shift();
            curLevel.push(node.val);
            // 存放当前层下一层的节点
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
        //把每一层的结果放到结果数组
        res.push(curLevel);
    }
    return res;
};

226.翻转二叉树

力扣题目链接(opens new window)

翻转一棵二叉树。

226.翻转二叉树

 226.翻转二叉树1

可以发现想要翻转它,其实就把每一个节点的左右孩子交换一下就可以了。

关键在于遍历顺序,前中后序应该选哪一种遍历顺序? (一些同学这道题都过了,但是不知道自己用的是什么顺序)

遍历的过程中去翻转每一个节点的左右孩子就可以达到整体翻转的效果。

注意只要把每一个节点的左右孩子翻转一下,就可以达到整体翻转的效果

这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!建议拿纸画一画,就理解了

那么层序遍历可以不可以呢?依然可以的!只要把每一个节点的左右孩子翻转一下的遍历方式都是可以的!

 

递归法

 

var invertTree = function(root) {
    if(!root) return null
    const queue = [root]
    while(queue.length){
        const node = queue.shift()
        const temp = node.left
        node.left = node.right
        node.right = temp
        if(node.left) queue.push(node.left)
        if(node.right) queue.push(node.right)
    }
    return root
}

//代码随想录的答案
//使用递归版本的前序遍历
var invertTree = function(root) {
    // 终止条件
    if (!root) {
        return null;
    }
    // 交换左右节点
    const rightNode = root.right;
    root.right = invertTree(root.left);
    root.left = invertTree(rightNode);
    return root;
};

// 使用迭代版本(统一模板))的前序遍历:
var invertTree = function(root) {
    //我们先定义节点交换函数
    const invertNode = function(root, left, right) {
        let temp = left;
        left = right;
        right = temp;
        root.left = left;
        root.right = right;
    }
    //使用迭代方法的前序遍历 
    let stack = [];
    if(root === null) {
        return root;
    }
    stack.push(root);
    while(stack.length) {
        let node = stack.pop();
        if(node !== null) {
            //前序遍历顺序中左右  入栈顺序是前序遍历的倒序右左中
            node.right && stack.push(node.right);
            node.left && stack.push(node.left);
            stack.push(node);
            stack.push(null);
        } else {
            node = stack.pop();
            //节点处理逻辑
            invertNode(node, node.left, node.right);
        }
    }
    return root;
};
// 使用层序遍历:
var invertTree = function(root) {
    //我们先定义节点交换函数
    const invertNode = function(root, left, right) {
        let temp = left;
        left = right;
        right = temp;
        root.left = left;
        root.right = right;
    }
    //使用层序遍历
    let queue = [];
    if(root === null) {
        return root;
    } 
    queue.push(root);
    while(queue.length) {
        let length = queue.length;
        while(length--) {
            let node = queue.shift();
            //节点处理逻辑
            invertNode(node, node.left, node.right);
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
    }
    return root;
};

101. 对称二叉树

力扣题目链接(opens new window)

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

101. 对称二叉树

 101. 对称二叉树1

 

var isSymmetric = function(root) {
    if(root === null) {
        return true;
    }
    let stack = [];
    stack.push(root.left);
    stack.push(root.right);
    while(stack.length) {
        let right = stack.pop();
        let left = stack.pop();
        if(left === null && right === null) {
            continue;
        }
        if(left === null || right === null) {
            return false;
        }
        if(left.val !== right.val) {
            return false;
        }
        stack.push(left.left);
        stack.push(right.right);
        stack.push(left.right);
        stack.push(right.left);
    }
    return true;
}
// @lc code=end
var root = {
    val: 1,
    left: {
        val: 2,
        left: {
            val: 3,
            left: null,
            right: null
        },
        right: {
            val: 4,
            left: null,
            right: null
        }
    },
    right: {
        val: 2,
        left: {
            val: 4,
            left: null,
            right: null
        },
        right: {
            val: 3,
            left: null,
            right: null
        }
    }
}
console.log(isSymmetric(root));

//代码随想录的方法
// 递归判断是否为对称二叉树:
var isSymmetric = function(root) {
    // 使用递归遍历左右子树 递归三部曲
    // 1. 确定递归的参数 root.left root.right和返回值true false 
    const compareNode = function(left, right) {
        // 2. 确定终止条件 空的情况
        if(left === null && right !== null || left !== null && right === null) {
            return false;
        } else if(left === null && right === null) {
            return true;
        } else if(left.val !== right.val) {
            return false;
        }
        // 3. 确定单层递归逻辑
        let outSide = compareNode(left.left, right.right);
        let inSide = compareNode(left.right, right.left);
        return outSide && inSide;
    }
    if(root === null) {
        return true;
    }
    return compareNode(root.left, root.right);
};

// 队列实现迭代判断是否为对称二叉树:
var isSymmetric = function(root) {
    // 迭代方法判断是否是对称二叉树
    // 首先判断root是否为空
    if(root === null) {
        return true;
    }
    let queue = [];
    queue.push(root.left);
    queue.push(root.right);
    while(queue.length) {
        let leftNode = queue.shift();    //左节点
        let rightNode = queue.shift();   //右节点
        if(leftNode === null && rightNode === null) {
            continue;
        }
        if(leftNode === null || rightNode === null || leftNode.val !== rightNode.val) {
            return false;
        }
        queue.push(leftNode.left);     //左节点左孩子入队
        queue.push(rightNode.right);   //右节点右孩子入队
        queue.push(leftNode.right);    //左节点右孩子入队
        queue.push(rightNode.left);    //右节点左孩子入队
    }
    
    return true;
  };

//   栈实现迭代判断是否为对称二叉树:
var isSymmetric = function(root) {
    // 迭代方法判断是否是对称二叉树
    // 首先判断root是否为空
    if(root === null) {
        return true;
    }
    let stack = [];
    stack.push(root.left);
    stack.push(root.right);
    while(stack.length) {
        let rightNode = stack.pop();    //左节点
        let leftNode=stack.pop();       //右节点
        if(leftNode === null && rightNode === null) {
            continue;
        }
        if(leftNode === null || rightNode === null || leftNode.val !== rightNode.val) {
            return false;
        }
        stack.push(leftNode.left);      //左节点左孩子入队
        stack.push(rightNode.right);    //右节点右孩子入队
        stack.push(leftNode.right);     //左节点右孩子入队
        stack.push(rightNode.left);     //右节点左孩子入队
    }
    
    return true;
  };

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java面试题二-并发编程、IO、设计模式、通信/网络、JVM

本文目录如下&#xff1a;Java面试题(二)四、并发编程线程和进程的区别&#xff1f;守护线程是什么&#xff1f;创建线程有哪几种方式&#xff1f;线程有哪些状态&#xff1f;sleep() 和 wait() 有什么区别&#xff1f;线程的sleep()方法和yield()方法有什么区别&#xff1f;线…

KVM虚拟机安装Virtio驱动

KVM虚拟机安装Virtio驱动KVM服务器上配置Virtio驱动ISO文件Windows实例安装Virtio驱动Linux实例安装kvm驱动(一般不需要)KVM服务器上配置Virtio驱动ISO文件 参考&#xff1a;https://www.ibm.com/docs/zh/cloud-orchestrator/2.5.0.1?topicimages-installing-virtio-driver-k…

成功解决:尚硅谷中的谷粒商城前端项目运行依赖问题。【详细图解+问题说明+解决思路】

一个混迹于Github、Stack Overflow、开源中国、CSDN、博客园、稀土掘金、51CTO等 的野生程序员。 目标&#xff1a;分享更多的知识&#xff0c;充实自己&#xff0c;帮助他人 GitHub公共仓库&#xff1a;https://github.com/zhengyuzh 以github为主&#xff1a; 1、分享前端后端…

程序员超级书单:技术人必看

写在前面 电影一部两小时打底&#xff0c;却很少有人可以静下心看30分钟书。今天刷沸点摸鱼, 无意中摸到一条让我有写作冲动的鱼&#xff0c;开工几天了&#xff0c;大家应该都暗暗立下不少flag&#xff0c;比如坚持锻炼&#xff0c;再比如自己今年要看多少本书籍。 行业内卷…

舆情监控工具app推荐,舆情监控工具包括哪些?

舆情监控工具的目的是帮助组织了解公众对各种话题、问题或品牌的意见和情绪。它们可以从多种来源收集数据&#xff0c;包括社交媒体、新闻媒体、博客、论坛和评论区。舆情监控工具app推荐&#xff0c;舆情监控工具包括哪些? 一、舆情监控工具app推荐 TOOM舆情监控工具&…

算法基础集训(第31天)------>BFS之经典【走迷宫】

一&#xff1a;概念定义给定一个 nm 的二维整数数组&#xff0c;用来表示一个迷宫&#xff0c;数组中只包含 0 或 1&#xff0c;其中 0 表示可以走的路&#xff0c;1 表示不可通过的墙壁。最初&#xff0c;有一个人位于左上角 (1,1) 处&#xff0c;已知该人每次可以向上、下、左…

扎克伯格15年邮件曝光:AR/VR平台全盘细节,谈收购Unity的优势

近期一份2015年时扎克伯格的一封邮件曝光&#xff0c;文中解释了Facebook在VR领域的战略策略和VR对未来的影响等&#xff0c;揭露了但是Facebook在VR/AR方向上的全盘计划&#xff0c;同时曝光当时Facebook就有收购Unity的计划&#xff0c;值得一看。以下是摘要&#xff1a;1&am…

DarkNet框架实现分类任务避坑指南(附安装包)

声明&#xff1a;本文仅分享技术&#xff0c;无其他 文章目录***声明&#xff1a;本文仅分享技术&#xff0c;无其他***这个框架真的非常非常非常小众&#xff0c;入坑需谨慎DarkNet对编译环境有要求配置前的准备环节1、 DarkNet源码封装&#xff08;安装包如果失效了&#xff…

看这个就够了——ubuntu系统中的cuda cudnn cudatookit及pytorch使用

一.基本概念1.1 nvidia独立显卡独立显卡是指以独立板卡形式存在&#xff0c;可在具备显卡接口的主板上自由插拔的显卡。独立显卡具备单独的显存&#xff0c;不占用系统内存&#xff0c;而且技术上领先于集成显卡&#xff0c;能够提供更好的显示效果和运行性能。显卡作为电脑主机…

GooFuzz:一款基于OSINT方法的模糊测试工具

关于GooFuzz GooFuzz是一款基于OSINT方法的模糊测试工具&#xff0c;该工具基于Google Dork实现其功能。本质上来说&#xff0c;GooFuzz是一个Bash脚本&#xff0c;该脚本使用了Google Search技术来获取文件或目录中的敏感信息&#xff0c;而无需向目标Web服务器发送请求。 工…

ESP-IDF:字符和整形二维指针测试

ESP-IDF:字符和整形二维指针测试 /字符和整形二维指针测试/ void print19a(void ** cp) { cout<<"test char ** "<<endl; cout<<"cp "<<*((char **)cp)<<endl; char *s *((char **)cp); cout<<"cp "<&…

可信数字仓储(TDR)及其实践应用案例

数字资源长期保存活动是为了保存人类的科学文化遗产&#xff0c;为公众提供持续服务&#xff0c;并为未来提供历史证据。在对数字资源进行长期保存的过程中&#xff0c;不可避免地要面对环境、技术、人员等方面的改变&#xff0c;要让用户信任所获得的信息&#xff0c;保存活动…

华为车BU王军被停职,余承东独掌智能车业务丨HiEV独家

来自多个信息源的消息显示&#xff0c;华为智能汽车解决方案BU&#xff08;简称「车BU」&#xff09;正迎来多项人事调整。 据HiEV得知的信息&#xff0c;车BU COO、智能驾驶解决方案产品线总裁王军已被停职。这距王军最近一次公开露面&#xff0c;仅相隔半个月。1月14日&#…

haproxy相关

docker编译运行 创建Dockerfile文件FROM haproxy:2.6.8 COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg编译docker镜像 docker build -t my-haproxy .测试配置文件 docker run -it --rm --name haproxy-syntax-check my-haproxy haproxy -c -f /usr/local/etc/haproxy/…

【FreeRTOS】详细讲解FreeRTOS里中断管理并通过示例讲述其用法

文章目录中断函数解析FreeRTOS中断使用示例中断 大家看到中断后&#xff0c;有没有想到一个名词——异常呢&#xff1f;若大家想到了&#xff0c;但是记不起相关概念&#xff1b;或者是&#xff0c;大家没想到这个名词&#xff0c;没关系&#xff0c; 下面小编就给大家伙讲讲中…

VMware 虚拟机无法开机

在windows下安装VMware虚拟机&#xff0c;使用ubuntu18.04系统时&#xff0c;由于非正常关机或者硬盘内存不够&#xff0c;导致无法正常开机&#xff0c;现象如下&#xff1a;问题原因&#xff1a;第一&#xff1a;pillx4_smbus异常&#xff0c;需要禁用&#xff1b;第二&#…

全网最细------爬取4k高清大图

本次案例将教大家免费爬取4k高清大图&#xff0c;即使你是爬虫新手&#xff0c;也可以食用本次文章实现你的免费下载梦,话不多说&#xff0c;先看效果 网站视图: 看到这些图片你是否怦然心动&#xff0c;跟着我一起看下去. 一.思路分析 首先最基本的是获取每张图片的链接&a…

【JavaEE】并发编程(多线程)线程安全问题内存可见性指令重排序

目录 第一个问题&#xff1a;什么是线程安全问题&#xff1f; 第二个问题&#xff1a;为什么会出现线程安全问题&#xff1f; 第三个问题&#xff1a;如何解决多线程安全问题&#xff1f; 第四个问题&#xff1a;产生线程不安全的原因有哪些&#xff1f; 第五个问题&am…

模板进阶(包含特化)

非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中可将该参数当成常量…

CSS(基础,面试,常见用例)

CSS规则【*】CSS选择器一、 CSS选择器二、选择器匹配原理三、优先级 / 权重四、可继承 / 不可继承样式属性【*】盒模型一、盒模型二、box-sizing属性三、offsetWidth、clientWidth、scrollWidth**【*】em/px/rem/vh/vw的区别一、CSS单位二、px三、em四、rem五、vh、vw六、%百分…