【每日一题】二叉树中的伪回文路径

news2024/12/28 5:47:01

文章目录

  • Tag
  • 题目来源
  • 题目解读
  • 解题思路
    • 方法一:递归(DFS)
    • 方法二:位运算
  • 写在最后

Tag

【递归/DFS】【伪回文】【二叉树】【2023-11-25】


题目来源

1457. 二叉树中的伪回文路径


题目解读

伪回文路径指的是路径中的节点值经过重新排序之后可以形成回文数的路径。现在需要返回二叉树中所有从根节点到叶子节点的路径中伪回文路径的数目。


解题思路

伪回文的判断

首先来看一下伪回文路径的判断,核心是对于路径节点值的是否具有伪回文性,即将这些节点重新排列之后是否可以构成回文数。比如某条路径上的节点值依次为 2 1 1 ,经过重新排列之后可以形成 1 2 1 这样的回文数,这里的定义不是很清楚,请继续看下去,后面你就会发现其实本题中不需要细究是回文数还是回文串。以下暂且使用回文数来对这样的回文形式进行表达。

回文数分为偶数回文和奇数回文,偶数回文指的是回文数中的字符数量是偶数,根据回文的特性(从左往右与从右往左读到的数都是一致的),回文数中每个字符出现的数量都要是偶数。

奇数回文指的是回文数中的字符数量是奇数,根据回文的特性(从左往右与从右往左读到的数都是一致的),回文数中仅有一个字符出现的数量是奇数(放置在回文数的中心位置),其余字符的出现次数都是偶数。

综上,要判断一个路径节点是否是伪回文的,只需要统计节点中字符个数为奇数的数量 cnt,如果 cnt <= 0,那么就是伪回文的,否则不是。

超出空间限制

本题,最先想到的就是深搜,得到所有可能的数字路径,比如示例 1 中的所有路径为 {{2,3,3},{2,3,1},{2,1,1}},然后遍历统计每一个的 vector 中元素的个数,仅有一个或者零个元素个数是奇数,那么这个 vector就是伪回文的。但是,超出空间限制,关于空间限制,有个疑问,
LeetCode空间限制的思考 欢迎讨论。

方法一:递归(DFS)

在深搜的过程中记录这条路径中不同节点出现的次数,在遇到叶子节点时统计:

  • 如果奇数个节点值的个数 cnt <= 1,则该路径是伪回文的;
  • 否则不是。

具体地,使用一个哈希表 mp 来维护出现的节点的数量,设当前节点为 node,更新 ++mp[node->val]

  • 如果当前节点是叶子节点则调用 chek 函数来更新答案 ans
  • 否则,递归计算左、右子树;
  • 注意需要回溯的过程,即更新 --mp[node->val]

实现代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    int ans = 0;
public:
    void dfs(TreeNode* root, unordered_map<int, int>& mp){
        if(!root){
            return;
        }
        ++ mp[root->val];
        if(!root->left && !root->right){
            // 检查当前的路径是否是 伪回文,并更新答案
            check(mp);
        }

        dfs(root->left, mp);
        dfs(root->right, mp);
        -- mp[root->val];
    }

    void check(unordered_map<int, int>& mp){
        int cnt = 0;
        for(auto [_, freq] : mp){
            if(freq & 1){
                ++ cnt;
            }
        }
        if (cnt <= 1) {
            ++ ans;
        }
    }

    int pseudoPalindromicPaths (TreeNode* root) {
        unordered_map<int, int> mp;
        dfs(root, mp);
        return ans;
    }
};

复杂度分析

时间复杂度: O ( C × n ) O(C \times n) O(C×n),其中 C C C 是节点中不同元素的数量, n n n 是二叉树中节点数。二叉树中每个元素都会被访问到,每次访问的叶子节点判断是否为伪回文路径的时间复杂度为 O ( C ) O(C) O(C)

空间复杂度: O ( n ) O(n) O(n),深搜深度最深为 O ( n ) O(n) O(n)

方法二:位运算

我们可以使用二进制数来标记路径中的节点出现的数量,节点最多有 10 种,即从 09,如果某个节点值出现次数为偶数则对应位 1 << (node->val) 记为 0,如果某个节点值出现次数为奇数则对应位 1 << (node->val) 记为 1。我们使用 mask 来表示某条路径中节点出现次数的奇偶数情况,比如 100000011 表示节点值 019 出现次数均为奇数。当前节点 nodemask 更新为 mask ^= 1 << node->val

如果 mask 中只有一个 1 或者没有 1,那么去掉 1 之后,mask 就变成 0 了,那么判断

KaTeX parse error: Expected 'EOF', got '&' at position 6: mask&̲(mask−1)=0

是否成立,如果成立则说明 mask 中要么只有一个 1,要么全为 0

实现代码

代码来源 一步步优化:从数组到位运算(Python/Java/C++/Go/JS/Rust)。

class Solution {
public:
    int pseudoPalindromicPaths(TreeNode *root, int mask = 0) {
        if (root == nullptr) {
            return 0;
        }
        mask ^= 1 << root->val; // 修改 root->val 出现次数的奇偶性
        if (root->left == root->right) { // root 是叶子节点
            return (mask & (mask - 1)) == 0;
        }
        return pseudoPalindromicPaths(root->left, mask) +
               pseudoPalindromicPaths(root->right, mask);
    }
};

复杂度分析

时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( n ) O(n) O(n)


写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

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

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

相关文章

Linux基本指令汇总

本专栏内容为&#xff1a;Linux学习专栏&#xff0c;分为系统和网络两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握Linux。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;Linux从入门到精通 &#x1f69a;代码仓库&#xff1a;小…

buuctf web [极客大挑战 2019]PHP

提示有备份,dirsearch扫描网站备份 GitHub - maurosoria/dirsearch: Web path scanner下载.zip格式文件 解压到python目录下 在上图位置cmd打开窗口 输入python setup.py install安装dirseach 安装好后输入命令使用dirseach python dirseach.py -u http://44296191-973d-448…

电子学会C/C++编程等级考试2021年09月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:字符统计 给定一个由a-z这26个字符组成的字符串,统计其中哪个字符出现的次数最多。输入 输入包含一行,一个字符串,长度不超过1000。输出 输出一行,包括出现次数最多的字符和该字符出现的次数,中间以一个空格分开。如果有多…

微信消息推送说明

1 打开任务清单 2 编辑任务清单设置 名字解释 姓名&#xff1a;微信名字 内容&#xff1a;要发送消息 定时&#xff1a;从几点开始发送 每隔几分钟&#xff1a;每隔几分钟重复发送一次 重复次数&#xff1a;每隔几分钟重复发送几次 响玲&#xff1a;定时语音电话&#x…

Redis主从复制(新)

像一些大型的项目&#xff0c;为了保证系统的稳定性&#xff0c;会有一台Redis服务器专门作为主机(master)&#xff0c;还会有多台服务器作为从机(slave)&#xff0c;主机可专门用作写数据&#xff0c;然后根据配置和策略&#xff0c;自动将数据同步到从机&#xff0c;而从机专…

Redis数据备份和还原

Redis SAVE 命令用于创建当前数据库的备份文件&#xff0c;文件名默认为dump.rdb。备份数据库数据可以增强对数据的保护&#xff0c;提升数据的安全性。当数据不小心丢失或者被删除时&#xff0c;我们就可以通过相应的操作进行数据恢复。本节介绍 Redis 的数据备份和数据还原操…

mybatis的使用,mybatis的实现原理,mybatis的优缺点,MyBatis缓存,MyBatis运行的原理,MyBatis的编写方式

文章目录 MyBatis简介结构图Mybatis缓存&#xff08;一级缓存、二级缓存&#xff09;MyBatis是什么&#xff1f;mybatis的实现原理JDBC编程有哪些不足之处&#xff0c;MyBatis是如何解决这些问题的&#xff1f;Mybatis优缺点优点缺点映射关系 MyBatis的解析和运行原理MyBatis的…

浅谈安科瑞剩余电流继电器在智能建筑中的应用

摘要&#xff1a;分析了智能建筑应用剩余电流继电器的必要性&#xff0c;介绍了ASJ剩余电流继电器的主要功能、工作原理、分类情况和提出了在选择剩余电流保护断路器时的原则和注意事项。 Abstract: the necessity of applying residual current relay in intelligent buildin…

不同视频格式如何一键生成二维码?二维码视频制作在线技巧

现在通过扫码看视频是很多人在使用的一种方式&#xff0c;通过制作视频二维码来引导用户了解自己的内容&#xff0c;但是视频有很多种不同的格式&#xff0c;那么有什么方法能够将不同格式的视频生成二维码呢&#xff1f;下面来教大家一招&#xff0c;通过在线的视频二维码生成…

MLFlow 入门(Model管理,生命周期管理)

最近需求需要使用mlflow&#xff0c;去学习了下&#xff0c;记录。 简介 MLflow是一个开源平台&#xff0c;专门为了帮助机器学习的从业者和团队处理机器学习过程中的复杂性而设计的。MLflow关注机器学习项目的完整生命周期&#xff0c;确保每个阶段都是可管理的、可追溯的和可…

邮件泄密案例分析

近日&#xff0c;一起令人震惊的事件在美军方内部引发了广泛关注。据报道&#xff0c;美军方意外将数百万封包含敏感信息的邮件发至非洲国家马里。这些邮件涉及的内容十分广泛&#xff0c;包括军事行动计划、人员部署、战术策略等&#xff0c;甚至还有部分涉及国家安全和战略决…

前缀和——238. 除自身以外数组的乘积

文章目录 &#x1f377;1. 题目&#x1f378;2. 算法原理&#x1f365;解法一&#xff1a;暴力求解&#x1f365;解法二&#xff1a;前缀和&#xff08;积&#xff09; &#x1f379;3. 代码实现 &#x1f377;1. 题目 题目链接&#xff1a;238. 除自身以外数组的乘积 - 力扣&a…

2023.11.24 关于 请求转发 和 请求重定向 的区别

目录 请求转发&#xff08;forward&#xff09; 请求重定向&#xff08;redirect&#xff09; 二者区别 定义不同 请求方不同 数据共享不同 最终 URL 地址不同 代码实现不同 阅读下文之前 建议点击下方链接简单了解 Fiddle Fiddle 的安装与使用 请求转发&#xff08;fo…

基于UI交互意图理解的异常检测方法

美团到店平台技术部/质量工程部与复旦大学周扬帆教授团队开展了科研合作&#xff0c;基于业务实际场景&#xff0c;自主研发了多模态UI交互意图识别模型以及配套的UI交互框架。 本文从大前端质量保障领域的痛点出发&#xff0c;介绍了UI交互意图识别的方法设计与实现。基于UI交…

训练日志——logging

目录 基础使用日志的6个级别打印日志修改打印级别 高级应用logging的组成记录器Loggers处理器Handlers过滤器Filterformatter格式创建关联打印日志 配置文件参考 基础使用 日志的6个级别 打印日志 import logginglogging.debug(调试日志) logging.info(消息日志) logging.war…

开源vs闭源,处在大模型洪流中,向何处去?

文章目录 一、开源和闭源的优劣势比较1.1 开源优势1.2 闭源的优势 二、开源和闭源对大模型技术发展的影响2.1 数据共享2.2 算法创新2.3 业务拓展2.4 安全性和隐私2.5 社会责任和伦理 三、开源与闭源的商业模式比较3.1 盈利模式3.2 市场竞争3.3 用户生态3.4 创新速度 四&#xf…

基于浣熊算法优化概率神经网络PNN的分类预测 - 附代码

基于浣熊算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于浣熊算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于浣熊优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

MyBatis的解析和运行原理

文章目录 MyBatis的解析和运行原理MyBatis的工作原理 MyBatis的解析和运行原理 MyBatis编程步骤是什么样的&#xff1f; 1、 创建SqlSessionFactory 2、 通过SqlSessionFactory创建SqlSession 3、 通过sqlsession执行数据库操作 4、 调用session.commit()提交事务 5、 调用…

【JavaWeb】TomcatJavaWebHTTP

Tomcat&JavaWeb&HTTP 文章目录 Tomcat&JavaWeb&HTTP一、Tomcat1.1 版本选择及安装1.2 目录1.3 WEB项目部署的方式 二、IDEA中Java Web开发部署流程三、HTTP协议3.1 发展历程3.2 HTTP协议的会话方式3.3 请求报文3.4 响应报文 一、Tomcat Tomcat是Apache 软件基…

机器学习探索计划——KNN算法流程的简易了解

文章目录 数据准备阶段KNN预测的过程1.计算新样本与已知样本点的距离2.按照举例排序3.确定k值4.距离最近的k个点投票 scikit-learn中的KNN算法 数据准备阶段 import matplotlib.pyplot as plt import numpy as np# 样本特征 data_X [[0.5, 2],[1.8, 3],[3.9, 1],[4.7, 4],[6.…