训练营day18

news2025/6/9 22:50:46

513.找树左下角的值

力扣题目链接(opens new window)

给定一个二叉树,在树的最后一行找到最左边的值。

示例 1:

513.找树左下角的值

示例 2:

513.找树左下角的值1

var findBottomLeftValue = function(root) {
    let queue = [root];
    let res = root.val;
    while (queue.length) {
        let node = queue.shift();
        if (node.right) queue.push(node.right);
        if (node.left) queue.push(node.left);
        if (!queue.length) res = node.val;
        // if(!node.left && !node.right) res=node.val
    }
    return res;
}
// // 代码随想录
// 递归版本:
var findBottomLeftValue = function(root) {
    //首先考虑递归遍历 前序遍历 找到最大深度的叶子节点即可
    let maxPath = 0, resNode = null;
    // 1. 确定递归函数的函数参数
    const dfsTree = function(node, curPath) {
    // 2. 确定递归函数终止条件
        if(node.left === null && node.right === null) {
            if(curPath > maxPath) {
            maxPath = curPath;
            resNode = node.val;
            }
        }
        node.left && dfsTree(node.left, curPath+1);
        node.right && dfsTree(node.right, curPath+1);
    }
    dfsTree(root,1);
    return resNode;
};
// 层序遍历:
var findBottomLeftValue = function(root) {
    //考虑层序遍历 记录最后一行的第一个节点
    let queue = [];
    if(root === null) { 
        return null;
    }
    queue.push(root);
    let resNode;
    while(queue.length) {
        let length = queue.length;
        for(let i = 0; i < length; i++) {
            let node = queue.shift();
            if(i === 0) {
                resNode = node.val;
            }
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
    }
    return resNode;
};

 

#112. 路径总和

力扣题目链接(opens new window)

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例:  给定如下二叉树,以及目标和 sum = 22,

112.路径总和1

返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。

#

 

递归

可以使用深度优先遍历的方式(本题前中后序都可以,无所谓,因为中节点也没有处理逻辑)来遍历二叉树

  1. 确定递归函数的参数和返回类型

参数:需要二叉树的根节点,还需要一个计数器,这个计数器用来计算二叉树的一条边之和是否正好是目标和,计数器为int型。

再来看返回值,递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)
  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236. 二叉树的最近公共祖先 (opens new window)中介绍)
  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)

而本题我们要找一条符合条件的路径,所以递归函数需要返回值,及时返回,那么返回类型是什么呢?

如图所示:

112.路径总和 

 

let haspathsum = function(root, targetsum) {
    if (!root) return false;
    if (!root.left && !root.right) return targetsum === root.val;
    return haspathsum(root.left, targetsum - root.val) || haspathsum(root.right, targetsum - root.val);
};
// 代码随想录
// 递归法
let haspathsum = function (root, targetsum) {
    // 递归法
    const traversal = (node, cnt) => {
      // 遇到叶子节点,并且计数为0
      if (cnt === 0 && !node.left && !node.right) return true;
      // 遇到叶子节点而没有找到合适的边(计数不为0),直接返回
      if (!node.left && !node.right) return false;
  
      //  左(空节点不遍历).遇到叶子节点返回true,则直接返回true
      if (node.left && traversal(node.left, cnt - node.left.val)) return true;
      //  右(空节点不遍历)  
      if (node.right && traversal(node.right, cnt - node.right.val)) return true;
      return false;
    };
    if (!root) return false;
    return traversal(root, targetsum - root.val);
  
    // 精简代码:
    // if (!root) return false;
    // if (!root.left && !root.right && targetsum === root.val) return true;
    // return haspathsum(root.left, targetsum - root.val) || haspathsum(root.right, targetsum - root.val);
};
// 迭代
let hasPathSum = function(root, targetSum) {
    if(root === null) return false;
    let nodeArr = [root];
    let valArr = [0];
    while(nodeArr.length) {
        let curNode = nodeArr.shift();
        let curVal = valArr.shift();
        curVal += curNode.val;
        // 为叶子结点,且和等于目标数,返回true
        if (curNode.left === null && curNode.right === null && curVal === targetSum) {
            return true;
        }
        // 左节点,将当前的数值也对应记录下来
        if (curNode.left) {
            nodeArr.push(curNode.left);
            valArr.push(curVal);
        }
        // 右节点,将当前的数值也对应记录下来
        if (curNode.right) {
            nodeArr.push(curNode.right);
            valArr.push(curVal);
        }
    }
    return false;
};

106.从中序与后序遍历序列构造二叉树

力扣题目链接(opens new window)

根据一棵树的中序遍历与后序遍历构造二叉树。

注意: 你可以假设树中没有重复的元素。

例如,给出

中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [9,15,7,20,3] 返回如下的二叉树:

106. 从中序与后序遍历序列构造二叉树1

 

var buildTree=function(inorder,postorder){
    if(!inorder.length) return null;
    const rootVal=postorder.pop();
    const index=inorder.indexOf(rootVal);
    const root=new TreeNode(rootVal);
    root.left=buildTree(inorder.slice(0,index),postorder.slice(0,index));
    root.right=buildTree(inorder.slice(index+1),postorder.slice(index));
    return root;
}
//代码随想录
var buildTree = function(inorder, postorder) {
    if (!inorder.length) return null;
    const rootVal = postorder.pop(); // 从后序遍历的数组中获取中间节点的值, 即数组最后一个值
    let rootIndex = inorder.indexOf(rootVal); // 获取中间节点在中序遍历中的下标
    const root = new TreeNode(rootVal); // 创建中间节点
    root.left = buildTree(inorder.slice(0, rootIndex), postorder.slice(0, rootIndex)); // 创建左节点
    root.right = buildTree(inorder.slice(rootIndex + 1), postorder.slice(rootIndex)); // 创建右节点
    return root;
};

105.从前序与中序遍历序列构造二叉树

力扣题目链接(opens new window)

根据一棵树的前序遍历与中序遍历构造二叉树。

注意: 你可以假设树中没有重复的元素。

例如,给出

前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树:

105. 从前序与中序遍历序列构造二叉树

 

var buildTree = function(preorder, inorder) {
    if (preorder.length === 0) return null;
    let root = new TreeNode(preorder[0]);
    let index = inorder.indexOf(preorder[0]);
    root.left = buildTree(preorder.slice(1, index + 1), inorder.slice(0, index));
    root.right = buildTree(preorder.slice(index + 1), inorder.slice(index + 1));
    return root;
};
// 代码随想录
// 从前序与中序遍历序列构造二叉树
var buildTree = function(preorder, inorder) {
    if (!preorder.length) return null;
    const rootVal = preorder.shift(); // 从前序遍历的数组中获取中间节点的值, 即数组第一个值
    const index = inorder.indexOf(rootVal); // 获取中间节点在中序遍历中的下标
    const root = new TreeNode(rootVal); // 创建中间节点
    root.left = buildTree(preorder.slice(0, index), inorder.slice(0, index)); // 创建左节点
    root.right = buildTree(preorder.slice(index), inorder.slice(index + 1)); // 创建右节点
    return root;
  };

113. 路径总和ii

力扣题目链接(opens new window)

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

说明: 叶子节点是指没有子节点的节点。

示例: 给定如下二叉树,以及目标和 sum = 22,

113.路径总和ii1.png

#思路

113.路径总和ii要遍历整个树,找到所有路径,所以递归函数不要返回值!

如图:

113.路径总和ii

// // 代码随想录
let pathsum = function (root, targetsum) {
    // 递归法
    // 要遍历整个树找到所有路径,所以递归函数不需要返回值, 与112不同
    const res = [];
    const travelsal = (node, cnt, path) => {
      // 遇到了叶子节点且找到了和为sum的路径
      if (cnt === 0 && !node.left && !node.right) {
        res.push([...path]); // 不能写res.push(path), 要深拷贝
        return;
      }
      if (!node.left && !node.right) return; // 遇到叶子节点而没有找到合适的边,直接返回
      // 左 (空节点不遍历)
      if (node.left) {
        path.push(node.left.val);
        travelsal(node.left, cnt - node.left.val, path); // 递归
        path.pop(); // 回溯
      }
      // 右 (空节点不遍历)
      if (node.right) {
        path.push(node.right.val);
        travelsal(node.right, cnt - node.right.val, path); // 递归
        path.pop(); // 回溯
      }
      return;
    };
    if (!root) return res;
    travelsal(root, targetsum - root.val, [root.val]); // 把根节点放进路径
    return res;
  };
//   递归 精简版
var pathsum = function(root, targetsum) {
    //递归方法
    let respath = [],curpath = [];
    // 1. 确定递归函数参数
    const traveltree = function(node,count) {
        curpath.push(node.val);
        count -= node.val;
        if(node.left === null && node.right === null && count === 0) {
            respath.push([...curpath]);
        }
        node.left && traveltree(node.left, count);
        node.right && traveltree(node.right, count);
        let cur = curpath.pop();
        count -= cur;
    }
    if(root === null) {
        return respath;
    }
    travelTree(root, targetSum);
    return resPath;
};
// 迭代
let pathSum = function(root, targetSum) {
    if(root === null) return [];
    let nodeArr = [root];
    let resArr = []; // 记录符合目标和的返回路径
    let tempArr = [[]]; // 对应路径
    let countArr = [0]; //对应和
    while(nodeArr.length) {
        let curNode = nodeArr.shift();
        let curVal = countArr.shift();
        let curNodeArr = tempArr.shift();
        curVal += curNode.val;
        curNodeArr.push(curNode.val);
        // 为叶子结点,且和等于目标数,将此次结果数组push进返回数组中
        if (curNode.left === null && curNode.right === null && curVal === targetSum) {
            resArr.push(curNodeArr);
        }
        // 左节点,将当前的和及对应路径也对应记录下来
        if (curNode.left) {
            nodeArr.push(curNode.left);
            countArr.push(curVal);
            tempArr.push([...curNodeArr]);
        }
         // 右节点,将当前的和及对应路径也对应记录下来
        if (curNode.right) {
            nodeArr.push(curNode.right);
            countArr.push(curVal);
            tempArr.push([...curNodeArr]);
        }
    }
    return resArr;
};

 

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

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

相关文章

Blender——烘培记录

参考链接&#xff1a;Blender2.8基础三&#xff1a;贴图烘培篇Blender 材质如何导出到 UE 和 Unity 里使用贴图烘焙打开【渲染属性】面板&#xff0c;把【渲染引擎】改为【Cycles】。把【设备】改为GPU计算&#xff0c;可以加快烘培速度。创建一个【图像纹理】节点&#xff08;…

fastadmin后台表单文字过长,限制显示,鼠标悬停显示全部

问题&#xff1a;显示文字区域过长&#xff0c;影响用户体验感 解决措施&#xff1a; 特别注意&#xff1a; return "<span styledisplay: block;overflow: hidden;text-overflow: ellipsis;white-space: nowrap; title" row.contents ">" value …

ARM uboot源码分析1-启动第一阶段

一、start.S 引入 1、u-boot.lds 中找到 start.S 入口 (1) 在 C 语言中整个项目的入口就是 main 函数&#xff08;这是 C 语言规定的&#xff09;&#xff0c;所以譬如说一个有 10000 个.c 文件的项目&#xff0c;第一个要分析的文件就是包含了 main 函数的那个文件。 (2) 在…

分享75个JS焦点图代码,总有一款适合您

分享75个JS焦点图代码&#xff0c;总有一款适合您 75个JS焦点图代码下载链接&#xff1a;https://pan.baidu.com/s/1WuydBKN3eYd3H64lPXv0Fw?pwd0nq7 提取码&#xff1a;0nq7 Python采集代码下载链接&#xff1a;https://wwgn.lanzoul.com/iKGwb0kye3wj base_url "…

MySQL面试题:关系型数据库SQL和非关系型数据库NoSQL

文章目录一、四大非关系型数据库与关系型数据库的对比1. 关系型数据库2. 基于列的数据库3. 键值对存储4. 文档存储5. 图形数据库参考文章&#xff08;金文&#xff09;&#xff1a;四大非关系型数据库类型&#xff0c;你知道多少 参考文章&#xff1a;“行式存储”和“列式存储…

2022虎符CTF-WEB赛后复现

1、ezphp 参考Jacko师傅的这篇虎符CTF 写的已经很详细了&#xff0c;先简单梳理一下题目&#xff0c;题目与P师傅的这篇文章类似我是如何利用环境变量注入执行任意命令。简单来说就是不同的系统&#xff0c;他的system命令调用的命令不同。 php中调用system本质上是调用了sh…

UDP报文结构

UDP协议 基本特点&#xff1a;无连接、不可靠传输、面向数据报、全双工 UDP协议报文结构 &#xff0c;以下分别是种画法 对上图进行解释&#xff1a; UDP就会把载荷数据&#xff08;就通过UDP socket ,也就是send方法拿来的数据&#xff0c;基础上再在前面拼接上几个字节的…

appium ios真机自动化环境搭建运行(送源码)

appium ios真机自动化环境搭建&运行&#xff08;送源码&#xff09; 目录&#xff1a;导读 &#xff08;1&#xff09;安装JDK&#xff0c;并配置环境变量&#xff0c;方法如下&#xff1a; &#xff08;2&#xff09;安装Xcode、Xcode commandline tools和iOS模拟器 &…

如何判断反馈电路的类型-反馈类型-三极管

如何判断反馈电路的类型 反馈电路类型很多&#xff0c;可根据不同的标准分类&#xff1a; ①根据反馈的极性分&#xff1a;有正反馈和负反馈。 ②根据反馈信号和输出信号的关系分&#xff1a;有电压反馈和电流反馈。 ③根据反馈信号和输入信号的关系分&#xff1a;有串联反…

渗透测试 -- IP、端口信息收集

数据来源 01 IP信息收集 1&#xff09;IP反查域名 同IP网站查询&#xff0c;同服务器网站查询 - 站长工具 专业精准的IP库服务商_IPIP 2&#xff09;域名查询IP IP/IPv6查询&#xff0c;服务器地址查询 - 站长工具 或直接 ping 一下域名就会返回IP 3&#xff09;CDN 如…

补天平台安全问题收录情况分享记录

声明 本文是学习2017年上半年 补天平台漏洞收录分析报告. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 补天平台及补天白帽大会介绍 “补天平台”&#xff0c;成立于2013年3月&#xff0c;全称为“补天漏洞响应平台”。平台旨在收集散落在民间的安…

MySQL8.0之前实现row_number以及计算玩家连续登录天数

使用MySQL 5.7版本统计 玩家连续登录天数 原始数据 玩家同一天多次登录只保留一条 select DISTINCT(FROM_UNIXTIME(login_time,%Y-%m-%d)) as login_date,rid from t_log_login order by rid; 借助两个变量统计每个玩家登录日期对应的次数 SELECT * FROM(SELECT DISTINCT …

云镜CVE-2022-25578复现

CVE-2022-25578复现漏洞信息漏洞复现读取flag&#x1f349; shell来源&#xff1a;https://yunjing.ichunqiu.com/cve/detail/960?type1&pay2漏洞信息 漏洞名称taocms v3.0.2允许攻击者通过编辑.htaccess文件执行任意代码漏洞编号CVE-2022-25578危害等级超危漏洞类型任意…

day34|343. 整数拆分、96.不同的二叉搜索树

343. 整数拆分 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: n 10 输出: 36 解…

电子技术——共栅(共基)放大器

电子技术——共栅&#xff08;共基&#xff09;放大器 在本节我们学习IC中共栅&#xff08;共基&#xff09;放大器的配置&#xff0c;虽然我们之前在分立电路中学习过共栅&#xff08;共基&#xff09;放大器的配置。但是在IC中共栅&#xff08;共基&#xff09;放大器主要作为…

MES系统助力电子厂行业,打造高能效工厂

ES主要包括生产计划系统、工艺管理系统、质量管理系统、生产过程管理系统、设备管理系统、仓储管理系统及数据采集和统计分析系统等。实现生产过程可视化、可追溯。管理人员可以在管理界面对生产实时控制&#xff0c;从而根据需要精准调整生产&#xff0c;达到提高生产效率、缩…

算法与数据结构理解

目录1、数据结构与算法1.1 定义1.2 常见数据结构1.3 常用算法2、插入排序3、希尔排序4、归并排序1、数据结构与算法 1.1 定义 数据结构&#xff1a;是计算机中存储、组织数据的方式。具有一定逻辑关系&#xff0c;应用某种存储结构&#xff0c;并且封装了相应操作的数据元素集…

HTML浪漫动态表白代码+音乐(附源码)

HTML浪漫表白求爱(附源码)&#xff0c;内含4款浪漫的表白源码&#xff0c;可用于520&#xff0c;情人节&#xff0c;生日&#xff0c;求爱场景&#xff0c;下载直接使用。 直接上源码吧 一.红色爱心 1.效果 实际效果是动态的哦 2.源码 复制粘贴即可运行哦 <!DOCTYPE…

JVM 线程本地分配缓存TLAB

什么是TLAB 从内存模型而不是垃圾收集的角度&#xff0c;对 Eden 区域继续进行划分&#xff0c;JVM 为每个线程分配了一个私有缓存区域&#xff0c;它包含在 Eden 空间内 多线程同时分配内存时&#xff0c;使用 TLAB 可以避免一系列的非线程安全问题&#xff0c;同时还能提升…

一文读懂CXL协议

2001年&#xff0c;英特尔公布了第三代I/O技术——3GIO技术&#xff08;后更名为PCI Express&#xff0c;即PCIe&#xff09;&#xff0c;以高性能、高扩展性、高可靠性及出色的兼容性取代了包括AGP和PCI在内所有的内部总线并且不断升格。例如&#xff0c;2019年5月底公布的PCI…