力扣hot100:199. 二叉树的右视图/437. 路径总和 III(dfs/回溯/树上前缀和/哈希表)

news2024/11/15 14:19:20

文章目录

  • 一、LeetCode:199. 二叉树的右视图
  • 二、LeetCode:437. 路径总和 III

一、LeetCode:199. 二叉树的右视图

LeetCode:199. 二叉树的右视图
在这里插入图片描述
差点因为是个中等题打退堂鼓。其实比较简单。
右视图实际上只需要找到,每一层的最右边的那个结点即可。
dfs

  • 确保每次找到底层最右边的结点,时间复杂度 O ( n ) O(n) O(n)
class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        cur_floor = 0;
        rightNode(root,0);
        return ans;
    }
private:
    void rightNode(TreeNode * root,int floor){//找到当前层最靠右的结点
        if(!root) return;
        if(floor == cur_floor){
            ans.emplace_back(root->val);
            cur_floor++;
        }
        rightNode(root->right,floor + 1);
        rightNode(root->left, floor + 1);
        return;
    }
    int cur_floor;
    vector<int> ans;
};

实际上使用层序遍历更好理解,每次选择一层的最后一个节点就行!


二、LeetCode:437. 路径总和 III

LeetCode:437. 路径总和 III
在这里插入图片描述
这个问题使用dfs可以解决,不过实现起来比较复杂,时间复杂度是 O ( n 2 ) O(n^2) O(n2)。我们先考虑其他方法。

发现使用树上前缀和很容易解决,最坏时间复杂度也是 O ( n 2 ) O(n^2) O(n2),所以我们先考虑使用前缀和。
未优化的前缀和+dfs回溯

  • 最坏时间复杂度是 O ( n 2 ) O(n^2) O(n2)
  • 前缀和求和,需要考虑元素大小的问题,所以要使用long long
  • 对于每一个结点需要求其前缀和,以及以当前结点结尾的序列的值的总和是否存在等于targetSum
  • 向下递归左右子节点,向上回溯。

在这里插入图片描述

class Solution {
public:
    int pathSum(TreeNode* root, int targetSum) {
        if(!root) return 0;
        vector<long long> presum;
        presum.emplace_back(0);//导入前导0
        getNum(root,targetSum,presum);
        return Num;
    }
private:
    void getNum(TreeNode * root,int targetSum,vector<long long> & presum){
        if(!root) return;
        //压入当前值的前缀和
        presum.emplace_back(root->val + presum.back());

        //判断以当前结点结尾的序列是否存在targetSum,由于存在负值,因此无法提前break
        for(int i = presum.size() - 2;i >= 0;--i){
            if(presum.back() - presum.at(i) == targetSum){
                ++Num;
            }
        }
        //继续向下递归
        getNum(root->left,targetSum,presum);
        getNum(root->right,targetSum,presum);
        //弹出当前值回溯
        presum.pop_back();
        return;
    }
    int Num=0;
};

做过两数之和之后很容易想到使用哈希表直接查找使用存在所需要的值。

  • p r e s u m 1 − p r e s u m 2 = t a r g e t S u m presum1 - presum2 = targetSum presum1presum2=targetSum
  • p r e s u m 2 = p r e s u m 1 − t a r g e t S u m presum2 = presum1 - targetSum presum2=presum1targetSum

我们真的是需要哈希表找到需要的值吗?在这里我们只需要之前有多少个这样的值就行了!
因此哈希的key = 目标前缀和,value = 目标前缀和的个数

使用哈希优化的前缀和+dfs回溯

  • 哈希查找,每个结点查找一次,平均时间复杂度 O ( 1 ) O(1) O(1),整个时间复杂度为 O ( n ) O(n) O(n)
  • 使用std::unordered_map的count方法,返回值是01表示存在或不存在。
  • 必须先判断是否存在所需前缀和,再压入当前值。 原因是当前值和所需前缀和可能刚好相等,导致当前前缀和也变成了答案的一部分,但实际上它不能是答案的一部分相当于之前所说的是同一个前缀和了,这使得序列为空。

在这里插入图片描述

class Solution {
public:
    int pathSum(TreeNode* root, int target) {
        if(!root) return 0;
        targetSum = target;
        presum_num[0] = 1;//导入前导0
        getNum(root,0);
        return Num;
    }
private:
    void getNum(TreeNode * root,long long presum){
        if(!root) return;
        long long cur_presum = presum + root->val;

        //判断以当前结点结尾的序列是否存在targetSum
        if(presum_num.count(cur_presum - targetSum) != 0)
            Num += presum_num[cur_presum - targetSum];
        
        //压入当前值的前缀和
        presum_num[cur_presum]++;

        //继续向下递归
        getNum(root->left,cur_presum);
        getNum(root->right,cur_presum);
        //弹出当前值回溯
        if(presum_num[cur_presum] != 1) presum_num[cur_presum]--;
        else presum_num.erase(cur_presum);
        return;
    }
    int Num=0;
    int targetSum;
    unordered_map<long long,int> presum_num;
};

前缀和的方法如果之前接触过很容易想到,不过这里建议学习深度优先遍历的方法,更深入理解dfs。
dfs

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 实现两个递归函数:
    • 第一个函数dfs:以根结点开始向下求和,得到targetSumNum++
    • 第二个函数getNum:遍历所有树节点,每个结点调用dfs函数。

在这里插入图片描述

class Solution {
public:
    int pathSum(TreeNode* root, int target) {
        targetSum = target;
        getNum(root);
        return Num;
    }
private:
    void getNum(TreeNode * root){
        if(!root) return;
        dfs(root,0);//包含本结点向下递归
        getNum(root->left);
        getNum(root->right);
        return;
    }
    void dfs(TreeNode * root,long long sum){
        if(!root) return;
        if(root->val + sum == targetSum) Num++;
        dfs(root->left,sum + root->val);
        dfs(root->right,sum + root->val);
        return;
    }
    int Num = 0;
    int targetSum;
};

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

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

相关文章

编译 x264 for iOS

文章目录 编译在 FFMpeg 启用 x264其他编译选项报错处理 环境 &#xff1a; macOS 14.3.1 x264 - 20191217-2245 编译 1、下载 x264 源码 http://download.videolan.org/pub/videolan/x264/snapshots/ 这里我下载x264-snapshot-20191217-2245.tar.bz2 &#xff08;截止2024-…

sql注入工具-​sqlmap

介绍&#xff1a; sqlmap是一款开源的自动化SQL注入工具&#xff0c;用于自动化检测和利用Web应用程序中的SQL注入漏洞。它具有强大的参数化查询和自定义注入脚本的功能&#xff0c;可以通过检测和利用SQL注入漏洞来获取数据库的敏感信息&#xff0c;如用户名、密码和其他重要…

Dockerfile镜像实例

目录 一、构建SSH镜像 1. 建立工作目录 2. 生成镜像 3. 启动容器并修改root密码 二、systemctl镜像 1. 建立工作目录 2. 生成镜像 3. 运行镜像容器 ​编辑 4. 测试容器systemct 三、Nginx镜像 1. 建立工作目录 2. 编写Dockerfile脚本 3. 编写run.sh启动脚本 4. …

Java之SimpleDateFormat

系列文章目录 文章目录 系列文章目录前言前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 在多线程环境下,当多个线程同时使用相同的SimpleDateFormat对象(如stat…

数据结构---时间复杂度+空间复杂度

算法(algorithm)简单说就是解决问题的方法。方法有好坏&#xff0c;同样算法也是&#xff0c;有效率高的算法&#xff0c;也有效率低的算法。衡量算法的好坏一般从时间和空间两个维度衡量&#xff0c;也就是本文要介绍的时间复杂度和空间复杂度。有些时候&#xff0c;时间与空间…

(三)JVM实战——对象的内存布局与执行引擎详解

对象的内存布局 对象的实例化 对象的创建方式 - new的方式 - Class的newInstance():反射的方式 - Construct的newInstance() - clone:实现Cloneable接口,默认浅拷贝 - 使用反序列化&#xff1a;将二进制流转化为内存对象 创建对象的步骤 - 判断对象对应的类是否加载、链接、初…

RabbitMQ之生产批量发送

为什么要用生产批量发送&#xff1f; 批量发送消息&#xff0c;可以提高MQ发送性能。但是 RabbitMQ 并没有提供了批量发送消息的 API 接口,使用 spring-amqp 的 BatchingRabbitTemplate 实现批量能力。 SimpleBatchingStrategy 发送策略满足以下规则会进行发送&#xff1a; ba…

扩展学习|国内外用户画像相关进展一览

文献来源&#xff1a;徐芳,应洁茹.国内外用户画像研究综述[J].图书馆学研究,2020(12):7-16.DOI:10.15941/j.cnki.issn1001-0424.2020.12.002. 一、用户画像的概念 用户画像概念一经提出,便被广泛应用到精准营销等领域。后来,作为一种描绘用户特征、表达用户诉求的有效工具,用户…

Angular进阶-NVM管理Node.js实现不同版本Angular环境切换

一、NVM介绍 1. NVM简介 Node Version Manager&#xff08;NVM&#xff09;是一个用于管理多个Node.js版本的工具。它允许用户在同一台机器上安装和使用多个Node.js版本&#xff0c;非常适合需要同时进行多个项目的开发者。NVM是开源的&#xff0c;支持MacOS、Windows和Linux…

LLM应用:工作流workflow创建自定义模版使用

参考: https://www.coze.cn/ 本案例是在coze平台上操作的,也有其他工具支持工作流的创建例如dify;也例如图像生成的comfyui工作流工具 创建自定义模版 可以根据自己需求创建自己的工作流工具;本文案例是创建一个联网搜索的LLM应用: 创建工作流页面: https://www.coze.c…

Java面试——不安全的集合类

​ 系统性学习&#xff0c;移步IT-BLOG-CN Java 中有许多的集合&#xff0c;常用的有List&#xff0c;Set&#xff0c;Queue&#xff0c;Map。 其中 List&#xff0c;Set&#xff0c;Queue都是Collection&#xff08;集合&#xff09;&#xff0c;List中<>的内容表示其中…

Linux CPU 飙升 排查五步法

排查思路-五步法 1. top命令定位应用进程pid 找到最耗时的CPU的进程pid top2. top-Hp[pid]定位应用进程对应的线程tid 找到最消耗CPU的线程ID // 执行 top -Hp [pid] 定位应用进程对应的线程 tid // 按shift p 组合键&#xff0c;按照CPU占用率排序 > top -Hp 111683.…

华为手机ip地址怎么切换

随着移动互联网的普及&#xff0c;IP地址成为了我们手机上网的重要标识。然而&#xff0c;在某些情况下&#xff0c;我们可能需要切换手机的IP地址&#xff0c;以更好地保护个人隐私、访问特定地区的内容或服务&#xff0c;或者出于其他网络需求。华为手机作为市场上的热门品牌…

【uniapp】H5+、APP模拟浏览器环境内部打开网页

前言 今天将智能体嵌入到我的项目中&#xff0c;当作app应用时&#xff0c;发现我使用的webview组件&#xff0c;无论H5怎么登录都是未登录&#xff0c;而APP却可以&#xff0c;于是进行了测试&#xff0c;发现以下几种情况&#xff1a; 方法<a>标签webviewAPP✅✅网页…

Spring扩展点(一)Bean生命周期扩展点

Bean生命周期扩展点 影响多个Bean的实例化InstantiationAwareBeanPostProcessorBeanPostProcessor 影响单个Bean的实例化纯粹的生命周期回调函数InitializingBean&#xff08;BeanPostProcessor 的before和after之间调用&#xff09;DisposableBean Aware接口在生命周期实例化过…

Hive大数据任务调度和业务介绍

目录 一、Zookeeper 1.zookeeper介绍 2.数据模型 3.操作使用 4.运行机制 5.一致性 二、Dolphinscheduler 1.Dolphinscheduler介绍 架构 2.架构说明 该服务内主要包含: 该服务包含&#xff1a; 3.FinalShell主虚拟机启动服务 4.Web网页登录 5.使用 5-1 安全中心…

[入门] Unity Shader前置知识(5) —— 向量的运算

在Unity中&#xff0c;向量无处不在&#xff0c;我想很多人都使用过向量类的内置方法 normalized() 吧&#xff0c;我们都知道该方法是将其向量归一化从而作为一个方向与速度相乘&#xff0c;以达到角色朝任一方向移动时速度都相等的效果&#xff0c;但内部具体是如何将该向量进…

【计算机科学速成课】笔记二

笔记一 文章目录 7.CPU阶段一&#xff1a;取指令阶段阶段二&#xff1a;解码阶段阶段三&#xff1a;执行阶段 8.指令和程序9.高级CPU设计——流水线与缓存 7.CPU CPU也叫中央处理器&#xff0c;下面我们要用ALU&#xff08;输入二进制&#xff0c;会执行计算&#xff09;、两种…

STM32之HAL开发——ADC入门介绍

ADC简介 模数转换&#xff0c;即Analog-to-Digital Converter&#xff0c;常称ADC&#xff0c;是指将连续变量的模拟信号转换为离散的数字信号的器件&#xff0c;比如将模温度感器产生的电信号转为控制芯片能处理的数字信号0101&#xff0c;这样ADC就建立了模拟世界的传感器和…

C++异常处理实现(libstdc++)

摘要&#xff1a;为了更好的理解C中异常处理的实现&#xff0c;本文简单描述了Itanium ABI中异常处理的流程和llvm/libsdc简要实现。 关键字&#xff1a;C,exception,llvm,clang C他提供了异常处理机制来对程序中的错误进行处理&#xff0c;避免在一些异常情况下无法恢复现场而…