leetcode刷题之有关树的算法

news2024/11/17 15:52:00

144.二叉树的前序遍历

方法一:递归

var preorderTraversal = function(root) {
    let arr = []
    const preorder = root =>{
        //递归的出口
        if(root==null){
            return
        }
        arr.push(root.val)
        preorder(root.left)
        preorder(root.right)
    }
    preorder(root)
    return arr
};

方法二:迭代 使用栈

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
         优秀是一种习惯                    迭代实现
 */
var preorderTraversal = function(root) {
    if(!root) return []
    let arr = []
    let stack = [root]
    while(stack.length){
        let node = stack.pop()
        arr.push(node.val)
        node.right&&stack.push(node.right)
        node.left&&stack.push(node.left)
    }
    return arr
};

94.二叉树的中序遍历

方法一:递归

var inorderTraversal = function(root) {
    //递归 
    let arr = []
    const inorder = root =>{
        if(!root) return []
        inorder(root.left)
        arr.push(root.val)
        inorder(root.right)
    }
    inorder(root)
    return arr
};

方法二:迭代

var inorderTraversal = function(root) {
    //迭代
    let arr = []
    let stack = []
    //也就是 root == null
    if(!root) return []
    //左节点一直入栈
    while(root){
        stack.push(root)
        root = root.left
    }
    //开始出栈
    while(stack.length){
        let node = stack.pop()
        arr.push(node.val)
        let temp = node.right
        //当前的结点出栈之后,检查其右侧结点的情况 依次入栈
        while(temp){
            stack.push(temp)
            temp = temp.left
        }
    }
    return arr
};

145.二叉树的后序遍历

方法一:递归

var postorderTraversal = function(root) {
    //递归
    let arr = []
    const postorder = root =>{
        //递归出去的条件
        if(!root) return 
        postorder(root.left)
        postorder(root.right)
        arr.push(root.val)
    }
    postorder(root)
    return arr
};

方法二:迭代 使用栈

var postorderTraversal = function(root) {
    //先将root的值放入到arr中,然后将root.right left 最终得到的结果与后序遍历的结果正好相反
    let arr = []
    let stack = [root]
    if(!root) return []
    while(stack.length){
        let node = stack.pop()
        arr.push(node.val)
        node.left&&stack.push(node.left)
        node.right&&stack.push(node.right)
    }
    return arr.reverse()
};

102.二叉树的层序遍历

方法一:递归

var levelOrder = function(root) {
    //递归实现
    let arr = []
    const level = (root,i) =>{
        if(!root) return
        level(root.left,i+1)
        // arr[i] = arr[i]?arr[i].push(root.val):[root.val]
        arr[i]?arr[i].push(root.val):arr[i] = [root.val]
        level(root.right,i+1)
    }
    level(root,0)
    return arr
};

方法二:迭代 使用队列

/**
 * @param {TreeNode} root
 * @return {number[][]}
 层序遍历相当于广度优先遍历 需要借助一个队列   
 */
var levelOrder = function(root) {
    //使用队列
    let arr = []
    let queue = [root]
    let i = 0
    if(!root) return []
    while(queue.length){
        //记录当前队列的长度
        let len = queue.length
        //用来存储当前层结点
        let tempArr = []
        for(let i=0;i<len;i++){
            //出队
            let node = queue.shift()
            tempArr.push(node.val)
            node.left&&queue.push(node.left)
            node.right&&queue.push(node.right)
        }
        arr.push(tempArr)
    }
    return arr
};

617.合并二叉树

在这里插入图片描述

方法一:递归

当看不懂递归的时候,参考二叉树的递归执行过程

var mergeTrees = function(root1, root2) {
    //使用递归
    const merge = (root1,root2) =>{
        //递归跳出的条件
        if(root1==null){
            return root2
        }
        if(root2==null){
            return root1
        }
        //创建新的结点
        //递归的过程是 ①创建newNode 调用27行的递归 一直到左侧递归的最深层次,返回一个root 返回上一个递归函数(这个递归函数会继续执行28行递归,直到其right结点全都为空)  真的很复杂
        let newNode = new TreeNode(root1.val+root2.val)
        newNode.left = merge(root1.left,root2.left)
        newNode.right = merge(root1.right,root2.right)
        return newNode
    }
    return merge(root1,root2)
};

//这里直接修改root1
var mergeTrees = function(root1, root2) {
   //重新去写一遍
   const merge = (root1,root2) =>{
       //递归的出口
       if(root1==null){
           return root2
       }
       if(root2==null){
           return root1
       }
       //这里用的是前序遍历
       root1.val += root2.val
       root1.left = merge(root1.left,root2.left)
       root1.right = merge(root1.right,root2.right)
       //返回上一层递归
       return root1
   }
   return merge(root1,root2)
};

方法二:使用队列

var mergeTrees = function(root1, root2) {
   //root1 root2进入同一个栈
   if(root1==null) return root2
   if(root2==null) return root1
   let queue = []
   queue.push(root1)
   queue.push(root2)
   while(queue.length){
       let node1 = queue.shift()
       let node2 = queue.shift()
       node1.val += node2.val
       if(node1.left!==null&&node2.left!==null){
           queue.push(node1.left)
           queue.push(node2.left)
       }
       if(node1.left==null&&node2.left!==null){
           node1.left = node2.left
       }
       if(node1.right&&node2.right){
           queue.push(node1.right)
           queue.push(node2.right)
       }
       if(node1.right==null&&node2.right!==null){
           node1.right = node2.right
       }
   }
   return root1
};

226.翻转二叉树

在这里插入图片描述

方法一:递归

/**
 * @param {TreeNode} root
 * @return {TreeNode}
 整个树的交换过程中,会把真个node结点下面的所有的结点都会交换过来
 */
var invertTree = function(root) {
    //递归实现
    if(!root) return root
    const invert = root =>{
        //递归出去的条件
        if(root==null) return null
        //递归
        let temp = invert(root.left)
        root.left = invert(root.right)
        root.right = temp
        return root
    }
    return invert(root)
};

方法二:前序遍历过程中实现交换

/**
 * @param {TreeNode} root
 * @return {TreeNode}
 整个树的交换过程中,会把真个node结点下面的所有的结点都会交换过来
 */
var invertTree = function(root) {
    //前序遍历的过程中实现翻转
    if(root==null) return root
    if(root.left==null&&root.right==null) return root
    let stack = [root]
    while(stack.length){
        //出栈
        let node = stack.pop()
        //进行交换  如果node.left不存在 那么node.left=null
        let temp = node.left
        node.left = node.right
        node.right = temp
        //入栈
        node.left&&stack.push(node.left)
        node.right&&stack.push(node.right)
    }
    return root
};

方法三:层序遍历过程中实现交换

var invertTree = function(root) {
    //层序遍历过程中实现
    if(root==null) return root
    if(root.left==null&&root.right==null) return root
    let queue = [root]
    while(queue.length){
        //出队
        let node = queue.shift()
        //进行交换
        let temp = node.left
        node.left = node.right
        node.right = temp
        //入队
        node.left&&queue.push(node.left)
        node.right&&queue.push(node.right)

    }
    return root
};

101.对称二叉树

在这里插入图片描述

方法一:递归

var isSymmetric = function(root) {
    //同时进去两个节点 left and right
    const compare = (root1,root2) =>{
        if(root1==null&&root2==null){
            return true
        }else if(root1==null&&root2!==null || root1!==null&&root2==null){
            return false
        }else if(root1.val!==root2.val){
            return false
        }
        //递归持续下去的条件  左右都得满足
        let outside = compare(root1.left,root2.right)
        let inside  = compare(root1.right,root2.left)
        return outside&&inside
    }
    return compare(root.left,root.right)
};

方法二:使用队列

var isSymmetric = function(root) {
    //队列实现
    if(root==null){
        return true
    }else if(root.left==null&&root.right==null){
        return true
    }else if(root.left!==null&&root.right==null || root.left==null&&root.right!==null){
        return false
    }
    
    let queue = []
    queue.push(root.left)
    queue.push(root.right)
    while(queue.length){
        let node1 = queue.shift()
        let node2 = queue.shift()
        if(node1.val!==node2.val){
            return false
        }
        if(node1.left==null&&node2.right!==null || node1.left!==null&&node2.right==null){
            return false
        }
        if(node1.right==null&&node2.left!==null || node1.right!==null&&node2.left==null){
            return false
        }
        node1.left&&queue.push(node1.left)
        node2.right&&queue.push(node2.right)
        node1.right&&queue.push(node1.right)
        node2.left&&queue.push(node2.left)
    }
    return true
};


//或者
var isSymmetric = function(root) {
    //队列实现
    if(root==null){
        return true
    }
    //入队   先去入队 出队的时候再去判断是否为空
    let queue = []
    queue.push(root.left)
    queue.push(root.right)
    //如果root.left right都是空的话  就不会有下面的while循环 直接跳出去了
    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) {
    //栈实现
    let stack = []
    if(root==null){
        return true
    }
    stack.push(root.left)
    stack.push(root.right)
    while(stack.length){
        let leftNode = stack.pop()
        let rightNode = 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
};

543.二叉树的直径

在这里插入图片描述

var diameterOfBinaryTree = function(root) {
  //二叉树的直径==根节点左右两侧高度之和的最大值
  let res = 0 //用来记录递归过程中遇到的和的最大值
  if(!root) return 0
  const diameter = root =>{
      if(root==null) return 0
      let leftHeight = diameter(root.left)
      let rightHeight = diameter(root.right)
      res = Math.max(res,(leftHeight+rightHeight))
      return Math.max(leftHeight,rightHeight)+1   //这是返回给上一层递归的结果值
  }
  diameter(root)
    return res
};

104.二叉树的最大深度

在这里插入图片描述

方法一:层序遍历之后,计算res的length

var maxDepth = function(root) {
   //方法一:层序遍历之后,将其放入到数组中,然后判断数组的长度
   let res = []
   if(root==null) return 0
   const level = (root,i) =>{
       if(root==null){
           return
       }
       //中序遍历的过程中进行压栈处理
       level(root.left,i+1)
       res[i]?res[i].push(root.val):res[i]=[root.val]
       level(root.right,i+1)
   }
   level(root,0)
   return res.length
};

//层序遍历过程中 不进行压栈处理
var maxDepth = function(root) {
   //层序遍历的过程中动态记录最大的深度
   let max = 0
   if(root==null) return 0
   const level = (root,i)=>{
       if(root==null){
           return
       }
       level(root.left,i+1)
       max = Math.max(max,i)
       level(root.right,i+1)
   }
   level(root,0)
   return max+1
};

方法二:同二叉树最大直径的求解过程

var maxDepth = function(root) {
   //利用二叉树最大直径的处理过程中 类似
   const maxit = root =>{
       if(root==null) return 0
       let leftHeight = maxit(root.left)
       let rightHeight = maxit(root.right)
       return Math.max(leftHeight,rightHeight) +1
   }
   return maxit(root) 
};

方法三:使用队列

var maxDepth = function(root) {
   //使用队列
   if(root==null) return 0
   let queue = [root]
   let arr = []
   while(queue.length){
       let len = queue.length
       let temp = []
       for(let i=0;i<len;i++){
           let node = queue.shift()
           temp.push(node.val)    
           node.left&&queue.push(node.left)
           node.right&&queue.push(node.right)
       }
       arr.push(temp)
   }
   return arr.length
};



//优化
var maxDepth = function(root) {
   //使用队列
   if(root==null) return 0
   let queue = [root]
   let max = 0
   while(queue.length){
       let len = queue.length
       for(let i=0;i<len;i++){
           let node = queue.shift()    
           node.left&&queue.push(node.left)
           node.right&&queue.push(node.right)

       }
       max++
   }
   return max
};

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

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

相关文章

Cell:癌症研究的下一个问题是什么?

人类对自身肿瘤发生和癌症进展的理解以及不同癌症类型的临床治疗在近年来发生了巨大的变化。然而&#xff0c;即使有这些进展&#xff0c;科学家和肿瘤学家仍然面临着许多挑战&#xff0c;从揭示其中的分子和细胞机制到治疗和生物标志物的开发&#xff0c;再到治疗后的生活质量…

【游戏逆向】《某某明月刀》BUFF及技能预判

为了提高游戏的可玩性&#xff0c;也为了提高外挂制作的难度&#xff0c;很多游戏对BOSS的技能伤害都设计的特别高&#xff0c;为了达到及时躲避的效果&#xff0c;我们需要对技能做预判。预判的方式有很多&#xff0c;比如通过收包的方式&#xff0c;这种方式判断的速度最快&a…

( 数组和矩阵) 667. 优美的排列 II ——【Leetcode每日一题】

❓667. 优美的排列 II 难度&#xff1a;中等 给你两个整数 n 和 k &#xff0c;请你构造一个答案列表 answer &#xff0c;该列表应当包含从 1 到 n 的 n 个不同正整数&#xff0c;并同时满足下述条件&#xff1a; 假设该列表是 answer [a1, a2, a3, ... , an] &#xff0…

【VM服务管家】VM4.2软件使用_5.4 工具类

目录 1.2.1 平移旋转标定&#xff1a;平移旋转标定模块的使用方法1.2.2 旋转标定&#xff1a;旋转标定模块的使用方法1.2.3 单点抓取&#xff1a;单点抓取模块的使用方法1.2.4 单点纠偏&#xff1a;单点纠偏模块的使用方法1.2.5 单点对位&#xff1a;单点映射对位模块的使用方法…

【PyTorch入门教程】1. 基础知识

欢迎关注 【LearnOpenCV: PyTorch入门教程】 PyTorch入门&#xff1a;Ch1 基础知识 PyTorch入门&#xff1a;[Ch2 使用预训练模型进行图像分类] PyTorch入门&#xff1a;[Ch3 使用迁移学习进行图像分类] PyTorch入门&#xff1a;[Ch4 使用ONNX和Caffe2进行模型推理] PyTorch入门…

中国机器人及人工智能大赛

报名 报名网站&#xff1a;https://www.caairobot.com 报名时&#xff0c;请在队伍名称后边添加任务后缀&#xff0c;比如&#xff0c;“诚朴-A”表明 队伍名称诚朴队&#xff0c;报名完成任务 A 然后在大赛官方 QQ 群 633244198&#xff08;智慧农业-机器人及人工智能大赛&…

力扣刷题215.数组中的第K个最大元素

215.数组中的第K个最大元素 215.数组中的第K个最大元素题目描述思路暴力解法堆排序快速排序 215.数组中的第K个最大元素 215. 数组中的第K个最大元素 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素…

Postman+Java springboot演示 get post put delete请求并携带(路径 路径问号后 json 表单)参数形式

我们先创建一个java的springboot工程 在项目中 找到启动类的位置目录 在项目创建一个类 叫 user 我是想将 user 当做一个属性类的 按规范来讲 我们可以创建一个entity包 然后在下面去创建属性类 但这里 我们不想搞那么麻烦了 毕竟只是练习一下 然后 user参考代码如下 package…

【Java校招面试】基础知识(五)——GC

目录 前言一、基础概念二、垃圾回收算法三、垃圾收集器四、引用后记 前言 本篇主要介绍Java垃圾回收机制——GC的相关内容。 “基础知识”是本专栏的第一个部分&#xff0c;本篇博文是第五篇博文&#xff0c;如有需要&#xff0c;可&#xff1a; 点击这里&#xff0c;返回本专…

【重新定义matlab强大系列五】函数filloutliers检测并替换数据中的离群值

&#x1f517; 运行环境&#xff1a;matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f91…

PyCharm下载、安装、注册以及简单使用【全过程讲解】

在使用PyCharm IDE之前&#xff0c;请确保自己的计算机里面安装了Python解释器环境&#xff0c;若没有下载和安装可以看看我之前的文章>>>Python环境设置>>>或者还可以观看视频讲解。 注意&#xff1a;本文软件的配置方式仅供个人学习使用&#xff0c;如有侵…

有研究员公开了一个解析并提取 Dell PFS BIOS 固件的工具(下)

导语&#xff1a;研究员公开了一个解析并提取 Dell PFS BIOS 固件的工具。 Apple EFI IM4P分配器 介绍 解析苹果多个EFI固件.im4p文件&#xff0c;并将所有检测到的EFI固件分割为单独的SPI/BIOS映像。 使用 你可以拖放或手动输入包含Apple EFI IM4P固件的文件夹的完整路径。…

【VM服务管家】VM4.2平台SDK_6.3 控件嵌入类

目录 2.3.1 渲染控件&#xff1a;渲染控件上自定义图形的方法2.3.2 参数控件&#xff1a;参数配置控件绑定模块的方法2.3.3 控件颜色&#xff1a;控件颜色修改方法2.3.4 独立控件&#xff1a;二次开发单独显示Group的方法2.3.5 取流控件&#xff1a;实时取流控件的使用方法2.3.…

【2023年第十一届泰迪杯数据挖掘挑战赛】B题:产品订单的数据分析与需求预测 23页论文及实现代码

【2023年第十一届泰迪杯数据挖掘挑战赛】B题&#xff1a;产品订单的数据分析与需求预测 23页论文及实现代码 相关链接 &#xff08;1&#xff09;建模方案 【2023年第十一届泰迪杯数据挖掘挑战赛】B题&#xff1a;产品订单的数据分析与需求预测 建模及python代码详解 问题一…

python为什么长期霸占榜首

Python霸占榜首 只因它真的很强 Python&#xff0c;年龄可能比很多读者都要大&#xff0c;但是它在更新快速的编程界却一直表现出色&#xff0c;甚至有人把它比作是编程界的《葵花宝典》&#xff0c;只是Python的速成之法相较《葵花宝典》有过之而无不及。 Python简洁&#x…

【Hello Network】UDP协议

作者&#xff1a;小萌新 专栏&#xff1a;网络 作者简介&#xff1a;大二学生 希望能和大家一起进步 本篇博客简介&#xff1a;简单介绍传输层和UDP协议 UDP协议 传输层端口号端口号范围划分知名端口号端口号与进程netstat与iostatpidof UDP协议UDP协议格式udp的数据封装udp的数…

2.2磁盘分区

2.2 磁盘分区 一个磁盘可以被划分为多个分区&#xff0c;有一个磁盘并且将他们划分为C;D;E盘&#xff0c;那个C,D,E就是分区&#xff08;partition&#xff09;。 2.2.1 磁盘连接的方式与设备文件名的关系 个人计算机常见的磁盘接口有两种&#xff0c;分别是SATA与SAS接口&…

精品:Stimulsoft Forms 2023.2.2

Stimulsoft Forms 是一种用于创建、编辑、填写、发布、分发交互式表单和收集结果的工具。我们的产品可嵌入到应用程序中&#xff0c;并允许您创建各种自定义填充模板。丰富的功能使模板具有真正的交互性。用户会收到 PDF 格式的可填写表格&#xff0c;他们可以在任何支持此格式…

ZooKeeper安装与配置集群

简介: ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xff0c;提供的功能包括&#xff1a;配置维护、域名服务、分布…

ChatGPT初尝试——合并Excel表格【AI版】

ChatGPT真的能提升生产力吗&#xff1f;【AI版】 无意间的刷到的视频一、提需求二、ChatGPT用Python编写代码三、意外的解释四、ChatGPT改用Java编写代码五、GPT第二次生成Java代码尾巴 无意间的刷到的视频 晚上在家刷视频&#xff0c;突然看到一个在讲关于AI编程的视频&#…