力扣 二叉树 相关题目总结3

目录

一、 222 完全二叉树的节点个数

题目

题解

方法一:递归法

方法二:

二、257 二叉树的所有路径

题目

题解

方法一:递归法

方法二:回溯法

三、04 左叶子之和

题目

题解


一、 222 完全二叉树的节点个数

题目

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

提示:
树中节点的数目范围是[0, 5 * 104]
0 <= Node.val <= 5 * 104
题目数据保证输入的树是 完全二叉树

题解

方法一:递归法

其实这道题的最暴力的解法就是直接用递归来统计结点的个数,根本不需要考虑什么完全二叉树还是完美二叉树,递归在手,遇 tree 不愁。直接一行搞定碉堡了,这可能是我见过最简洁的 brute force 的解法了吧。

参见代码如下:

class Solution {
    public int countNodes(TreeNode root) {
        if(root == null) return 0;
        return 1 + countNodes(root.left) + countNodes(root.right);
    }
}

方法二:

(1)完全二叉树是一种特殊的二叉树,具有以下特点:

  1. 所有层,除了最后一层,都必须完全填满。
  2. 在最后一层,所有的节点尽可能地向左排列。

简而言之,完全二叉树的每一层都满了,只有最后一层可以不满,但节点必须从左到右依次填入。

        1
      /   \
     2     3
    / \   /
   4   5 6

(2)完美二叉树(也称为满二叉树)是一种更严格的二叉树,具有以下特点:

  1. 所有层都必须完全填满。
  2. 每个内部节点都有两个子节点,且所有叶节点都在同一层。

简而言之,完美二叉树的每一层都必须是满的。

        1
      /   \
     2     3
    / \   / \
   4   5 6   7

利用一下完全二叉树这个条件,通过上面对完全二叉树跟完美二叉树的定义比较,可以看出二者的关系是,完美二叉树一定是完全二叉树,而完全二叉树不一定是完美二叉树。

那么这道题给的完全二叉树就有可能是完美二叉树,若是完美二叉树,节点个数很好求,为2的h次方减1,h为该完美二叉树的高度。若不是的话,只能老老实实的一个一个数节点了。

思路是由 root 根结点往下,分别找最靠左边和最靠右边的路径长度,如果长度相等,则证明二叉树最后一层节点是满的,是满二叉树,直接返回节点个数,如果不相等,则节点个数为左子树的节点个数加上右子树的节点个数再加1(根节点),其中左右子树节点个数的计算可以使用递归来计算。

参见代码如下:

class Solution {
    public int countNodes(TreeNode root) {
        int lc = 0, rc = 0;
        TreeNode l = root;
        TreeNode r = root;
        while(l != null){
            ++lc;
            l = l.left;
        }
        while(r != null){
            ++rc;
            r = r.right;
        }

        if(lc == rc) return (int)Math.pow(2, lc) - 1;
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}

二、257 二叉树的所有路径

题目

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

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

提示:
树中节点的数目在范围 [1, 100] 内
-100 <= Node.val <= 100

题解

方法一:递归法

这里我们使用递归的方法来获取二叉树的所有路径,在我们对树进行递归遍历时,如果当前节点是叶子节点,说明我们就找到了一条满足条件的路径,如果当前节点不是叶子节点,那么就继续递归遍历左右子树,直到遍历到叶子节点。

代码如下,

public List<String> binaryTreePaths(TreeNode root) {
    List<String> res = new ArrayList<>();
    dfs(root,"",res);
    return res;
}
private static void dfs(TreeNode root, String path, List<String> list) {
    // 节点为空, 递归终止
    if (root == null) return;
    // 当前节点是叶子节点, 说明找到了一条路径, 加入结果列表中
    if (root.left == null && root.right == null) {
        list.add(path + root.val);
    }
    // 当前节点不是叶子节点, 则继续遍历左子树和右子树寻找路径
    dfs(root.left,path + root.val + "->",list);
    dfs(root.right,path + root.val + "->",list);
}

方法二:回溯法

提到根节点到叶子节点的路径,那一定就是先序遍历了。我们要拿到一条路径是很简单的,只要从根节点开始沿途一直寻找到叶子节点就可以了,本题的难点在于如何得到所有的路径。也就是当我们达到了叶子节点之后,还要回溯回去,换个方向找找还有没有其他的路径。 说到这里 —— 那么这道题就转化为一道回溯法的问题了。

  • 回溯法参数 : 当前遍历到的节点 root、 当前得到的路径 path
  • 结束条件 : 找到叶子节点,即左右子节点都为空的节点
  • 单层逻辑: 在路径中加入当前节点值 root.val,判断左子节点是否为空,不为空则递归调用左节点,然后回溯。对右子节点同理。

代码如下,定义主方法 binaryTreePaths,接受一个二叉树的根节点 root 作为参数,返回从根节点到叶节点的所有路径。创建一个局部列表 path 用于存储当前路径。调用辅助方法 backTrace 开始回溯遍历二叉树。

class Solution {
    public List<String> binaryTreePaths(TreeNode root){
        List<String> res = new ArrayList<>(); // 存最终的结果
        if(root == null) return res;
    
        List<Integer> paths = new ArrayList<>(); // 作为结果中的路径
        traversal(root, paths, res);
        return res;
    }

    private void traversal(TreeNode root, List<Integer> paths, List<String> res){
        paths.add(root.val); // 前序遍历,中
        // 遇到叶子结点
        if(root.left == null && root.right == null){
            // 输出
            StringBuilder sb = new StringBuilder(); // StringBuilder用来拼接字符串,速度更快
            for(int i = 0; i < paths.size() - 1; i++){
                sb.append(paths.get(i)).append("->");
            }
            sb.append(paths.get(paths.size() - 1)); // 记录最后一个结点
            res.add(sb.toString()); // 收集一个路径
            return;
        }
        // 递归和回溯是同时进行,所以要放在同一个花括号里
        if(root.left != null){ // 左
            traversal(root.left, paths, res);
            paths.remove(paths.size() - 1); // 回溯
        }
        if(root.right != null){ // 右
            traversal(root.right, paths, res);
            paths.remove(paths.size() - 1); // 回溯
        }
    }
}

三、04 左叶子之和

题目

给定二叉树的根节点 root ,返回所有左叶子之和。

提示:
节点数在 [1, 1000] 范围内
-1000 <= Node.val <= 1000

题解

这个题的解题思路:遍历 + 判断。

  • 遍历:遍历二叉树的所有节点
  • 判断:判断当前节点是否是左子节点,以及是否是叶子节点

只要一个节点满足判断中的两个条件,那么我们就可以将当前节点的节点值累加起来,如果当前节点是右子节点或者不是叶子节点,那么我们就继续递归的遍历它,就可以得到最终的答案。

大体流程如下:

  • 首先, 如果根节点root为null或者只有一个节点,则说明没有叶子节点,直接返回0;
  • 否则,添加一个递归方法recursive,有2个参数,分别是当前节点的左右子节点,flag为左右子节点的标识,递归过程如下:
    • 调用递归方法recursive,参数分别为root的左右子节点,flag为相应的标识;
      • 判断递归方法中的root如果为null,则返回;
      • 如果root没有左右子节点,且flag标识为左子节点,则将root的值加到结果result中;
      • 否则,递归调用recursive,参数分别为root的左右子节点,flag为相应的标识。
      • 最后,返回result即为所有的左叶子节点之和。

代码如下,

class Solution {
    public int result = 0;

    public int sumOfLeftLeaves(TreeNode root) {
       if (root == null || (root.left == null && root.right == null)) return 0;
       recursive(root.left, true);
       recursive(root.right, false);
       return result; 
    }

    public void recursive(TreeNode root, boolean flag) {
       if (root == null)  return;
       if (root.left == null && root.right == null && flag)  result += root.val;

       recursive(root.left, true);
       recursive(root.right, false);
   } 
}

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

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

相关文章

元服务体验-服务发现

服务发现&#xff0c;无论线上或线下的方式都可以发现元服务。 线上&#xff1a;基于用户意图。从精准意图的搜索、用户事件触发的推荐到主动探索等场景。用户可以在设备的负一屏、全局搜索、应用市场、桌面等场景发现元服务。 线下&#xff1a;用户在 HarmonyOS Connect标签…

网络安全 DVWA通关指南 DVWA Brute Force (爆破)

DVWA Brute Force (爆破) 文章目录 DVWA Brute Force (爆破)LowMediumHighImpossible Low 1、分析网页源代码 <?php// 检查是否存在"Login" GET 参数&#xff0c;这通常是提交登录表单后触发的动作 if( isset( $_GET[ Login ] ) ) {// 获取POST方式提交的用户名…

rancher单节点安装k8s

k3s 优点: 可用性 易于操作的轻量级部署模型 缺点: 与上游Kubernetes不同 RKE1 优点: 与上游Kubernetes紧密对齐 缺点: 严重依赖于 Docker RKE2 凭借 k3s 的优势和更紧密的上游协调&#xff0c;RKE2 将控制平面组件作为静态 pod 启动&#xff0c;由 kubelet 管理。 为了符合行业…

Gitlab CI/CD --- use a sample CI/CD template

0 Preface/Foreword Pipeline, job, stage的关系如下描述&#xff1a; A pipeline is composed of independent jobs that run scripts, grouped into stages. Stages run in sequential order, but jobs within stages run in parallel. 关键信息&#xff1a; pipeline由独…

前端路由手写Hash和History两种模式

文章目录 1. Hash模式&#xff1a;简洁而广泛适用2. History模式&#xff1a;更自然的用户体验3. 结论 在现代Web开发中&#xff0c;单页面应用&#xff08;Single Page Application&#xff0c;简称SPA&#xff09;因其流畅的用户体验和高效的页面交互能力而备受青睐。前端路由…

51单片机STC89C52RC——19.1 SG90舵机(伺服电机)

目的/效果 独立按键K1&#xff0c;K2 实现加舵机减角度增减&#xff0c;LCD1602显示舵机转角度数&#xff08;上电默认90度&#xff09; 一&#xff0c;STC单片机模块 二&#xff0c;SG90舵机 2.1 简介 舵机只是我们通俗的叫法&#xff0c;它的本质是一个伺服电机&#xf…

LeetCode-返回链表倒数第K个节点、链表的回文结构,相交链表

一、返回链表倒数第k个节点 . - 力扣&#xff08;LeetCode&#xff09; 本体思路参展寻找中间节点的方法&#xff0c;寻找中间节点是定义快慢指针&#xff0c;快指针每次走两步&#xff0c;慢指针每次走一步&#xff0c;当快指针为空或者快指针的下一个节点是空时&#xff0c;…

maven项目容器化运行之2-maven中使用docker插件调用远程docker构建服务并在1Panel中运行

一.背景 公司主机管理小组的同事期望我们开发的maven项目能够在1Panel管理的docker容器部署。上一篇写了先开放1Panel中docker镜像构建能力maven项目容器化运行之1-基于1Panel软件将docker镜像构建能力分享给局域网-CSDN博客。这一篇就是演示maven工程的镜像构建、容器运行、运…

TCP/IP地址管理

TCP/IP中使用IP地址来确定网络上的一台主机 IPV4协议中&#xff0c;32位&#xff08;4个字节&#xff09;源IP地址和32位目的IP地址&#xff0c;也就是可以表示2^3242亿9千万个地址 如今随着互联网甚至物联网的迅速发展&#xff0c;我们面临着IP地址数量不充足的问题&#xf…

一款IM即时通讯聊天系统源码,包含app和后台源码

一款IM即时通讯聊天系统源码 聊天APP 附APP&#xff0c;后端是基于spring boot开发的。 这是一款独立服务器部署的即时通讯解决方案&#xff0c;可以帮助你快速拥有一套自己的移动社交、 企业办公、多功能业务产品。可以 独立部署&#xff01;加密通道&#xff01;牢牢掌握通…

云备份服务端

文件使用工具和json序列化反序列化工具 //文件和json工具类的设计实现 #ifndef __UTIL__ #define __UTIL__ #include<iostream> #include<fstream> #include<string> #include <vector> #include<sys/stat.h> #include"bundle.h" #inc…

热门软件缺陷管理工具2024:专业评测与建议

国内外主流的10款软件缺陷管理工具软件对比&#xff1a;PingCode、Worktile、禅道、Tapd、Teambition、Tower、JIRA、Bugzilla、MantisBT、Trac。 在软件开发过程中&#xff0c;管理缺陷和漏洞常常成为一项挑战&#xff0c;尤其是在项目规模庞大时。选择一个高效的软件缺陷管理…

【Linux环境sqlite下载安装教程】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、下载路径二、安装步骤 一、下载路径 https://sqlite.org/download.html 选择Alternative Source Code Formats下的sqlite-src-3460000.zip进行下载。 二、安…

手机怎么看WiFi的IP地址

在如今数字化快速发展的时代&#xff0c;无线网络已成为我们日常生活中不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;我们可能都离不开WiFi的陪伴。然而&#xff0c;在使用WiFi的过程中&#xff0c;有时我们可能需要查看其IP地址&#xff0c;以便更好地管理我们的网…

Jira学习

1.Dev OPS DevOps简介 DEV OPS 流程 DEV OPS流程对应工具 最重要的就是持续集成–Jenkins 2.Jira 新建项目

华为HCIP Datacom H12-821 卷39

1.填空题 请2001 :0DB8:0000:C030:0000: 000: 09A0:CDEF地址进行压缩。() (若答案中存在字母&#xff0c;请采用大写格式) 参考答案&#xff1a;2001 :DB8:0:C030: :9A0:CDEF 解析&#xff1a; IPv6地址的表示方法 IPv6地址总长度为128比特&#xff0c;通常分为8组&#xff0c…

macos上latex环境搭建(homebrew安装+vscode配置+ MacTex)和B站视频、网站、教程等相关资料推荐(Overleaf、公式预览网站)

安装及配置 本机环境 本人为macos&#xff0c;已经安装了homebrew和vscode。希望得到的效果是在vscode中编辑并预览latex文件 MacTex安装 首先&#xff0c;使用brew安装MacTex(新版本的brew已经将install和install --cask合并了) brew install mactex安装后一般会置于如下…

对于GPT-5在一年半后发布的期待!

首先&#xff0c;如果GPT-5真如OpenAI首席技术官米拉穆拉蒂&#xff08;Mira Murati&#xff09;在采访中所透露的那样&#xff0c;在一年半后发布&#xff0c;并在某些领域达到博士级的智能&#xff0c;这无疑将是一个令人振奋的消息。这一预测不仅反映了AI技术的快速发展&…

uniapp 微信小程序根据后端返回的文件链接打开并保存到手机文件夹中【支持doc、docx、txt、xlsx等类型的文件】!

项目场景&#xff1a; 我们在使用uniapp官方提供的uni.downloadFile以及uni.saveFile时&#xff0c;会发现这个文件下载的默认保存位置和我们预想的不太一样&#xff0c;容易找不到&#xff0c;而且没有提示&#xff0c;那么我们就需要把文件打开自己保存并且有提示保存到哪个…

leetcode算法题(反转链表)

思路1&#xff1a; 创建新的链表&#xff0c;遍历原链表&#xff0c;将原链表的节点进行头插到新链表中。 struct ListNode* reverseList(struct ListNode* head) {struct ListNode* next NULL;struct ListNode* new_head NULL;if (head NULL ||head->next NULL) // 空…