算法训练营 day18 二叉树 找树左下角的值 路径总和 从中序与后序遍历构建二叉树

news2024/11/20 15:20:59

算法训练营 day18 二叉树 找树左下角的值 路径总和 从中序与后序遍历构建二叉树

找树的左下角

513. 找树左下角的值 - 力扣(LeetCode)

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

递归法

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

参数必须有要遍历的树的根节点,还有就是一个int型的变量用来记录最长深度。 这里就不需要返回值了,所以递归函数的返回类型为void。

还需要类里的两个全局变量,maxLen用来记录最大深度,result记录最大深度最左节点的数值。

  1. 确定终止条件

当遇到叶子节点的时候,就需要统计一下最大的深度了,所以需要遇到叶子节点来更新最大深度。

  1. 确定单层递归的逻辑

在找最大深度的时候,递归的过程中依然要使用回溯,

class Solution {
    private int maxDepth = Integer.MIN_VALUE;
    private int result=0;
    public int findBottomLeftValue(TreeNode root) {
        if (root==null) return root.val;
        findLeftValue(root,0);
        return result;
    }
    private  void findLeftValue(TreeNode root, int depth) {
        if (root.left==null&&root.right==null){
            if (depth>maxDepth){
                maxDepth = depth;
                result = root.val;
            }
        }
        if (root.left!=null)findLeftValue(root.left,depth+1);
        if (root.right!=null)findLeftValue(root.right,depth+1);
    }
}

层序遍历

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        int result = 0;
        Queue<TreeNode> que = new LinkedList<>();
        TreeNode node;
        if (root == null) return root.val;
        que.add(root);
        while (!que.isEmpty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                node = que.poll();
                if (i == 0) result=node.val;
                if (node.left!=null) que.add(node.left);
                if (node.right!=null) que.add(node.right);
            }
        }
        return result;
    }
}

路径总和

112. 路径总和 - 力扣(LeetCode)

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

递归法

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

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

在这里插入图片描述

  1. 确定终止条件

首先计数器如何统计这一条路径的和呢?

不要去累加然后判断是否等于目标和,那么代码比较麻烦,可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。

如果最后count == 0,同时到了叶子节点的话,说明找到了目标和。

如果遍历到了叶子节点,count不为0,就是没找到

  1. 确定单层递归的逻辑

因为终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。

递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回。

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root==null) return false;

        if (root.left==null&&root.right==null) return root.val==targetSum;

        return hasPathSum(root.left,targetSum- root.val)||hasPathSum(root.right,targetSum-root.val);
    }
}

迭代法

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        Stack<TreeNode> st = new Stack<>();
        Stack<Integer> nums = new Stack<>();
        if (root==null) return false;
        st.push(root);
        nums.push(root.val);
        TreeNode node;
        int sum;
        while(!st.isEmpty()){
            node = st.pop();
            sum = nums.pop();
            if (node.left==null&&node.right==null&&sum==targetSum){
                return true;
            }
            if (node.left!=null){
                st.push(node.left);
                nums.push(sum+node.left.val);
            }
            if (node.right!=null){
                st.push(node.right);
                nums.push(sum+node.right.val);
            }
        }
        return false;
    }
}

再来一题

113. 路径总和 II - 力扣(LeetCode)

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

叶子节点 是指没有子节点的节点。

class Solution {
List<List<Integer>> result;
   LinkedList<Integer> path;
   public List<List<Integer>> pathSum (TreeNode root,int targetSum) {
       result = new LinkedList<>();
       path = new LinkedList<>();
       travesal(root, targetSum);
       return result;
   }
   private void travesal(TreeNode root,  int count) {
       if (root == null) return;
       path.offer(root.val);
       count -= root.val;
       if (root.left == null && root.right == null && count == 0) {
           result.add(new LinkedList<>(path));
       }
       travesal(root.left, count);
       travesal(root.right, count);
       path.removeLast(); // 回溯
   }
}

从中序与后序遍历构建二叉树

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

  • 第一步:如果数组大小为零的话,说明是空节点了。
  • 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
  • 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
  • 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
  • 第五步:切割后序数组,切成后序左数组和后序右数组
  • 第六步:递归处理左区间和右区间
class Solution {
    Map<Integer, Integer> map;  // 方便根据数值查找位置
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
            map.put(inorder[i], i);
        }

        return findNode(inorder,  0, inorder.length, postorder,0, postorder.length);  // 前闭后开
    }
    
    public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
        // 参数里的范围都是前闭后开
        if (inBegin >= inEnd || postBegin >= postEnd) {  // 不满足左闭右开,说明没有元素,返回空树
            return null;
        }
        int rootIndex = map.get(postorder[postEnd - 1]);  // 找到后序遍历的最后一个元素在中序遍历中的位置
        TreeNode root = new TreeNode(inorder[rootIndex]);  // 构造结点
        int lenOfLeft = rootIndex - inBegin;  // 保存中序左子树个数,用来确定后序数列的个数
        root.left = findNode(inorder, inBegin, rootIndex,
                            postorder, postBegin, postBegin + lenOfLeft);
        root.right = findNode(inorder, rootIndex + 1, inEnd,
                            postorder, postBegin + lenOfLeft, postEnd - 1);

        return root;
    }
}

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

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

相关文章

Java --- JUC之原子类

目录​​​​​​​ 一、基本类型原子类 二、数组类型原子类 三、引用类型原子类 四、对象的属性修改类型原子类 五、原子操作增强类 5.1、高性能热点商品应用 5.2、LongAdder架构图 5.3、源码分析 一、基本类型原子类 public class AtomicTest1 {public static final…

canvas:基础知识【直线和矩形】

canvas&#xff0c;就是画布&#xff0c;是HTML5和核心技术之一&#xff0c;结合JavaScript&#xff0c;可以绘制各种各样的图形&#xff0c;比如矩形、曲线、圆形等等。另外&#xff0c;canvas可以绘制图表、动画效果、游戏开发。 基本图形汇中有直线和曲线。常见的直线图形是…

arduino rc522模块使用

rfid IC卡 先了解IC卡一些前置知识。 首先我们会有一张ic卡&#xff08;M1类型IC卡&#xff0c;一般买到的都是1K存储空间&#xff09;&#xff0c;在rc522代码中会出现这个&#xff0c;就是对IC卡进行检查PICC_TYPE_MIFARE_4K和PICC_TYPE_MIFARE_1K就是一种卡片类型不同大小…

零基础学MySQL(二)-- 表的创建,修改,删除

文章目录&#x1f388;一、创建表1️⃣基本语法2️⃣入门案例&#x1f386;二、MySQL常用数据类型1️⃣数值型&#xff08;整型&#xff09;默认有符号2️⃣数值型&#xff08;bit&#xff09;3️⃣数值型&#xff08;浮点型&#xff09;默认有符号4️⃣字符串的基本使用5️⃣字…

1584_AURIX_TC275_SMU的调试以及部分寄存器

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) 前面学习的过程中&#xff0c;突然间减速了不少。但是为了保证学习的推进&#xff0c;还是得有每天的稳定输出。我的策略是多看&#xff0c;多处理&#xff0c;之后每天整理10页标注的文档…

设计模式相关内容介绍

1.学习设计模式好处 提高编程能力、思维能力、设计能力程序设计更加标准化、代码编制更加工程化&#xff0c;软件开发效率大大提高&#xff0c;缩短项目周期设计的代码可重用性高、可读性强、可靠性高、 灵活性好、可维护性强 2.设计模式分类 创建型模式 提供创建对象的机制…

一文读懂工业级交换机的规范使用

工业交换机具备电信级特性特点&#xff0c;可承受严苛的工作环境&#xff0c;产品种类丰富多彩&#xff0c;交换机配置灵便&#xff0c;可以满足各类工业应用的应用标准。那么&#xff0c;大家使用工业级交换机的过程当中应该如何规范使用呢&#xff1f; 工业级交换机其实质运…

蓝队攻击的四个阶段(四)

目录 一&#xff0c; 外网纵向突破 1.1 何为外网纵向突破 1.2外网纵向突破的主要工作 二&#xff0c; 外网纵向突破的途径 1. Web 网站 2.外部邮件系统 3.边界网络设备 4.外部应用平台 三&#xff0c;内网横向拓展 1. 1何为内网横向拓展 1.2 内网横向拓展的主要工作 …

电商价格监测,关注这些,才算实际到手价

品牌控价的第一项工作&#xff0c;是先找出低价乱价链接&#xff0c;这就需要进行电商价格监测。但是我们搜索品牌链接的时候&#xff0c;会发现网页上的价格是多种多样&#xff1a;有原价&#xff08;但是划掉了&#xff09;、促销价、折扣价、惊喜价&#xff0c;优惠活动也是…

localStorage

localStorage localStorage了解 有些数据确实需要存储在本地&#xff0c;但是它却不需要发送到服务器&#xff0c;所以并不适合放在cookie中 localStorage 也是一种浏览器存储数据的方式&#xff08;本地存储&#xff09;&#xff0c;它只是存储在本地&#xff0c;不会发送…

【Linux】进程间通信(1)

信号 什么是信号&#xff1f;信号是给程序提供一种可以处理异步事件的方法&#xff0c;它利用软件中断来实现。不能自定义信号&#xff0c;所有信号都是系统预定义的。 信号由谁产生&#xff1f; 由shell终端根据当前发生的错误&#xff08;段错误、非法指令等&#xff09;Ctr…

商品详情的APP原数据接口测试

一、原数据接口的来源&#xff1a; 原数据接口来源于手机端&#xff0c;随着智能化的发展与普及&#xff0c;越来越多的人都是使用智能手机&#xff0c;这样极大的方便了人民的生活&#xff0c;各大电商平台看准了这个商家&#xff0c;把目光都瞄准这个商机&#xff0c;伴随而…

BP靶场中SQL注入练习

BP靶场中SQL注入练习1.Bp靶场介绍1.1.访问靶场1.2.注意事项2.SQL注入靶场2.1.注意事项2.2.检索隐藏数据2.2.1.开启靶场2.2.2.点击礼物2.2.3.测试类型2.2.4.爆出全部物品(包括隐藏)2.3.登录逻辑2.3.1.开启靶场2.3.2.登录账户2.3.3.注释验证2.3.4.成功登陆2.4.判断列2.4.1.开启靶…

会话技术--cookie和session

一、会话跟踪技术的概述 对于会话跟踪这四个词&#xff0c;我们需要拆开来进行解释&#xff0c;首先要理解什么是会话&#xff0c;然后再去理解什么是会 话跟踪: 会话:用户打开浏览器&#xff0c;访问web服务器的资源&#xff0c;会话建立&#xff0c;直到有一方断开连接&#…

变量、作用域与内存

目录 原始值与引用值 动态属性 复制值 传递参数 确定类型 执行上下文与作用域 作用域链增强 变量声明 1.使用var 的函数作用域声明 2. 使用let 的块级作用域声明 3.使用const 的常量声明 标识符查找 垃圾回收 标记清理&#xff08;最常用&#xff09; 引用计数 内…

2022__我的嵌入式入坑之路

目录 一、学习篇 51单片机&#xff1a; python爬虫&#xff1a; stm32单片机&#xff1a; ad&#xff1a; 立创EDA&#xff1a; openmv&#xff1a; ardunio&#xff1a; ESP32&#xff1a; 汇编语言&#xff1a; ROS&#xff1a; FreeRTOS&#xff1a; matlab&a…

【学习】大数据关键技术

学习内容描述&#xff1a; 大数据涉及的四个环节是什么&#xff1f; 云计算服务的三种服务类型是什么&#xff1f; 重点知识&#xff1a; 大数据涉及的四个环节&#xff1a;1、数据采集&#xff1b;2、数据存储&#xff1b;3、数据管理&#xff1b;4、数据分析与挖掘。云计算…

大型智慧灌区信息化管理系统云平台 智慧灌区信息化管理系统解决方案

平升电子大型智慧灌区信息化管理系统云平台/智慧灌区信息化管理系统解决方案&#xff0c;对灌区的渠道水位、流量、水雨情、土壤墒情、气象等信息进行监测&#xff0c;同时对泵站、闸门进行远程控制&#xff0c;对重点区域进行视频监控&#xff0c;实现了信息的采集、统计、分析…

基于pyautogui的自动识别定位原神风物之诗琴按键弹奏程序

前言&#xff1a;为了学习pyautogui这个库的使用&#xff0c;我准备用它做点东西。比如一个自动弹琴的程序。不过这个琴不是现实里的琴&#xff0c;而是原神里的风物之诗琴。&#xff08;这里有个网页版模拟器可以试试&#xff1a;风物之诗琴模拟器 (haveyouwantto.github.io)&…

Spring 监听器listener原理

1.创建本地事件和事件监听器/*** 事件类*/ public class MyEventA extends ApplicationEvent {private static final long serialVersionUID 1L;public MyEventA(Object source) {super(source);System.out.println("MyEventA 构造方法被执行了...");}public void o…