力扣每日一题——连接两棵树后最大目标节点数目 ||
目录
题目链接:3373. 连接两棵树后最大目标节点数目 II - 力扣(LeetCode)
题目描述
解法一:双树贡献分离法
Java写法:
C++写法:
运行时间
时间复杂度和空间复杂度
总结
题目链接:3373. 连接两棵树后最大目标节点数目 II - 力扣(LeetCode)
注:下述题目描述和示例均来自力扣
题目描述
有两棵 无向 树,分别有 n
和 m
个树节点。两棵树中的节点编号分别为[0, n - 1]
和 [0, m - 1]
中的整数。
给你两个二维整数 edges1
和 edges2
,长度分别为 n - 1
和 m - 1
,其中 edges1[i] = [ai, bi]
表示第一棵树中节点 ai
和 bi
之间有一条边,edges2[i] = [ui, vi]
表示第二棵树中节点 ui
和 vi
之间有一条边。
如果节点 u
和节点 v
之间路径的边数是偶数,那么我们称节点 u
是节点 v
的 目标节点 。注意 ,一个节点一定是它自己的 目标节点 。
请你返回一个长度为 n
的整数数组 answer
,answer[i]
表示将第一棵树中的一个节点与第二棵树中的一个节点连接一条边后,第一棵树中节点 i
的 目标节点 数目的 最大值 。
注意 ,每个查询相互独立。意味着进行下一次查询之前,你需要先把刚添加的边给删掉。
示例 1:
输入:edges1 = [[0,1],[0,2],[2,3],[2,4]], edges2 = [[0,1],[0,2],[0,3],[2,7],[1,4],[4,5],[4,6]]
输出:[8,7,7,8,8]
解释:
- 对于
i = 0
,连接第一棵树中的节点 0 和第二棵树中的节点 0 。 - 对于
i = 1
,连接第一棵树中的节点 1 和第二棵树中的节点 4 。 - 对于
i = 2
,连接第一棵树中的节点 2 和第二棵树中的节点 7 。 - 对于
i = 3
,连接第一棵树中的节点 3 和第二棵树中的节点 0 。 - 对于
i = 4
,连接第一棵树中的节点 4 和第二棵树中的节点 4 。
示例 2:
输入:edges1 = [[0,1],[0,2],[0,3],[0,4]], edges2 = [[0,1],[1,2],[2,3]]
输出:[3,6,6,6,6]
解释:
对于每个 i
,连接第一棵树中的节点 i
和第二棵树中的任意一个节点。
提示:
2 <= n, m <=
edges1.length == n - 1
edges2.length == m - 1
edges1[i].length == edges2[i].length == 2
edges1[i] = [ai, bi]
0 <= ai, bi < n
edges2[i] = [ui, vi]
0 <= ui, vi < m
- 输入保证
edges1
和edges2
都表示合法的树。
解法一:双树贡献分离法
这道题的解法可以称为双树贡献分离法。咱们分两部分来说,解核心思路和具体实现。
首先,问题的核心在于两棵树之间只能连一条边的情况下,如何最大化第一棵树每个节点的目标节点数。这里的关键在于发现:连接后的贡献可以拆分为原本树内的贡献和通过新边获得的第二棵树贡献。举个例子,假设我们在第一棵树的节点A和第二棵树的节点B之间连边,那么A的目标节点数就等于A在原本树里的可达节点数加上B在另一棵树里能带来的额外节点数。
这里整个过程分两步走:第一步要算出第一棵树每个节点自身在k步内能到达多少个目标节点,这一步可以用DFS遍历整棵树,记录每个节点在限定步数内能找到的节点数。第二步要找出第二棵树中哪个节点能在k-1步内覆盖最多的节点(因为跨树连接需要消耗一步边权),这时候同样用DFS遍历第二棵树的所有节点,找到最大值。
这里有个比较巧妙的地方:当k=0时根本不能跨树连接,所以这时候第二棵树的贡献直接为零;当k≥1时,跨树后的剩余步数是k-1,这时候只要找到第二棵树中能覆盖最多节点的那个节点即可。整个过程不需要真正连接所有可能的节点对,而是通过预处理两棵树各自的贡献,最后直接相加得到结果。
实现时要注意两点:1. 使用DFS时要避免重复访问父节点,通过记录父节点指针来防止回头路;2. 在计算第二棵树的贡献时,只需要保留最大值而不需要记录每个节点的贡献,这样能节省内存空间。整个过程的时间复杂度主要取决于两棵树的节点数和k值的大小,属于典型的树遍历问题优化方案。
这种解法把看似复杂的连接问题拆解成了两个独立的子问题,最后通过简单相加得到结果,既避免了暴力枚举所有可能的连接方式,又保证了算法效率,算是个典型的分治思想在树结构中的应用。
Java写法:
import java.util.*;public class Solution {public int[] maxTargetNodes(int[][] edges1, int[][] edges2) {List<List<Integer>> tree1 = buildTree(edges1);List<List<Integer>> tree2 = buildTree(edges2);// 计算两棵树的层级奇偶分布int[] layerCount1 = computeLayerCounts(tree1);int[] layerCount2 = computeLayerCounts(tree2);// 第二棵树的最大贡献int maxSecond = Math.max(layerCount2[0], layerCount2[1]);// 获取第一棵树每个节点的层级int[] nodeLayers = getNodeLayers(tree1);// 计算结果int[] ans = new int[tree1.size()];for (int i = 0; i < ans.length; i++) {int currentLayer = nodeLayers[i] % 2;ans[i] = (currentLayer == 0 ? layerCount1[0] : layerCount1[1]) + maxSecond;}return ans;}// 构建邻接表private List<List<Integer>> buildTree(int[][] edges) {int n = edges.length + 1;List<List<Integer>> tree = new ArrayList<>();for (int i = 0; i < n; i++) tree.add(new ArrayList<>());for (int[] e : edges) {tree.get(e[0]).add(e[1]);tree.get(e[1]).add(e[0]);}return tree;}// 计算奇偶层节点数(BFS实现)private int[] computeLayerCounts(List<List<Integer>> tree) {int[] layers = new int[tree.size()];Arrays.fill(layers, -1);Queue<Integer> queue = new LinkedList<>();queue.add(0);layers[0] = 0;while (!queue.isEmpty()) {int u = queue.poll();for (int v : tree.get(u)) {if (layers[v] == -1) {layers[v] = layers[u] + 1;queue.add(v);}}}int even = 0, odd = 0;for (int layer : layers) {if (layer % 2 == 0) even++;else odd++;}return new int[]{even, odd};}// 获取每个节点的层级(BFS实现)private int[] getNodeLayers(List<List<Integer>> tree) {int[] layers = new int[tree.size()];Arrays.fill(layers, -1);Queue<Integer> queue = new LinkedList<>();queue.add(0);layers[0] = 0;while (!queue.isEmpty()) {int u = queue.poll();for (int v : tree.get(u)) {if (layers[v] == -1) {layers[v] = layers[u] + 1;queue.add(v);}}}return layers;}
}
C++写法:
#include <vector>
#include <queue>
using namespace std;class Solution {
public:vector<int> maxTargetNodes(vector<vector<int>>& edges1, vector<vector<int>>& edges2) {auto tree1 = buildTree(edges1);auto tree2 = buildTree(edges2);auto [even1, odd1] = computeLayerCounts(tree1);auto [even2, odd2] = computeLayerCounts(tree2);int maxSecond = max(even2, odd2);auto nodeLayers = getNodeLayers(tree1);vector<int> ans(tree1.size());for (int i = 0; i < ans.size(); ++i) {ans[i] = (nodeLayers[i] % 2 ? odd1 : even1) + maxSecond;}return ans;}private:vector<vector<int>> buildTree(vector<vector<int>>& edges) {int n = edges.size() + 1;vector<vector<int>> tree(n);for (auto& e : edges) {tree[e[0]].push_back(e[1]);tree[e[1]].push_back(e[0]);}return tree;}pair<int, int> computeLayerCounts(vector<vector<int>>& tree) {vector<int> layers(tree.size(), -1);queue<int> q;q.push(0);layers[0] = 0;while (!q.empty()) {int u = q.front();q.pop();for (int v : tree[u]) {if (layers[v] == -1) {layers[v] = layers[u] + 1;q.push(v);}}}int even = 0, odd = 0;for (int l : layers) {(l % 2 == 0) ? even++ : odd++;}return {even, odd};}vector<int> getNodeLayers(vector<vector<int>>& tree) {vector<int> layers(tree.size(), -1);queue<int> q;q.push(0);layers[0] = 0;while (!q.empty()) {int u = q.front();q.pop();for (int v : tree[u]) {if (layers[v] == -1) {layers[v] = layers[u] + 1;q.push(v);}}}return layers;}
};
运行时间
时间复杂度和空间复杂度
- 时间复杂度:O(nk + mk)(DFS)或 O(n² + m²)(BFS)。
- 空间复杂度:O(n + m + k)。
总结
阿巴阿巴
相关文章:

力扣每日一题——连接两棵树后最大目标节点数目 ||
目录 题目链接:3373. 连接两棵树后最大目标节点数目 II - 力扣(LeetCode) 题目描述 解法一:双树贡献分离法 Java写法: C写法: 运行时间 时间复杂度和空间复杂度 总结 题目链接:…...

【学习笔记】Sparse Crosscoders for Cross-Layer Features and Model Diffing
Sparse Crosscoders for Cross-Layer Features and Model Diffing Abstract 本说明介绍了稀疏跨编码器(sparse crosscoders),它是一种稀疏自编码器(sparse autoencoders)或transcoders的变体,旨在用于理解叠加中的模型结构。SAEs是在单一层中编码和预测…...

VSCode无法转到定义python源码(ctrl加单击不跳转)
已经尝试的方案: 1.确保对应python环境正确激活 在 VSCode 中,打开命令面板(CtrlShiftP),输入并选择 Python: Select Interpreter,然后从列表中选择正确的 Python 解释器。 2.重新卸载Python插件再重新安装…...

【华为战报】4月、5月 HCIP考试战报!
了解更多往期考试→点 【考试战报】 华为认证 HCIP 4、5月微思 | HCIP 考试战报 学员成绩单 华为认证 最新开班 厦门面授 全国直播 新生代网工必看:华为模拟器eNSP安装教程(附下载链接)...
开发指南120-表格(el-table)斑马纹
el-table实现斑马纹简单否,看起来很简单,网上给的例子都是加stripe,例如 <el-table :data"tableData" stripe>连官网上的例子都是这样。然并卵。也许是版本问题。这么写,怎么折腾都没有效果。 必须这样写才行 …...
数字化转型全场景安全解析:从产品到管理的防线构建与实施要点
在数字化转型中,安全已从“可选配置” 升级为 “必需底座”,贯穿于产品生命周期、生产过程、供应链及管理决策全场景。以下从南京市场景清单出发,结合技术实践与政策要求,分析安全在各核心场景中的具体内涵与实施要点:…...

AIGC工具平台-GPT-SoVITS-v4-TTS音频推理克隆
声音克隆与语音合成的结合,是近年来生成式AI在多模态方向上的重要落地场景之一。随着预训练模型能力的增强,结合语音识别、音素映射与TTS合成的端到端系统成为初学者可以上手实践的全流程方案。 围绕 GPT-SoVITS-v4-TTS 模块,介绍了其在整合…...

el-table配置表头固定而且高度变化
根据官网提示只要在 el-table 元素中定义了 height 属性,即可实现固定表头的表格,而不需要额外的代码。 如果你想既要固定表头,又要下方表格高度自适应,可以设置为 height"100%" : 然后外层设置scroll:...

设计模式——组合设计模式(结构型)
摘要 组合设计模式是一种结构型设计模式,用于将对象组合成树形结构以表示“部分-整体”的层次结构,使客户端对单个对象和组合对象具有一致的访问方式。它包含抽象组件、叶子节点和组合节点,具有统一处理、支持递归结构和易扩展等优点&#x…...
PostgreSQL 在生物信息学中的应用
PostgreSQL(简称PG)是一种强大的开源关系型数据库管理系统,因其高可靠性、扩展性和支持复杂查询的特性,在生物信息学领域得到广泛应用。以下是其核心应用场景及优势分析: 一、生物数据存储与管理 生物信息学涉及海量…...

EMO2:基于末端执行器引导的音频驱动虚拟形象视频生成
今天带来EMO2(全称End-Effector Guided Audio-Driven Avatar Video Generation)是阿里巴巴智能计算研究院研发的创新型音频驱动视频生成技术。该技术通过结合音频输入和静态人像照片,生成高度逼真且富有表现力的动态视频内容,值得…...
计算机总线技术深度解析:从系统架构到前沿演进
计算机系统中的总线是连接多个部件的信息传输线,是各部件间传输信息的公共通道。以下将从总线的定义、功能、分类、性能指标等方面进行详细介绍: 一、总线的定义与功能 1.定义:总线是一组能为多个部件分时共享的公共信息传送线路࿰…...

Python打卡训练营Day43
DAY 43 复习日 作业: kaggle找到一个图像数据集,用cnn网络进行训练并且用grad-cam做可视化 数据集地址:Lung Nodule Malignancy 肺结核良恶性判断 进阶:并拆分成多个文件 import os import pandas as pd import numpy as np from…...

PHP7+MySQL5.6 查立得轻量级公交查询系统
# PHP7MySQL5.6 查立得轻量级公交查询系统 ## 系统简介 本系统是一个基于PHP7和MySQL5.6的轻量级公交查询系统(40KB级),支持线路查询、站点查询和换乘查询功能。系统采用原生PHPMySQL开发,无需第三方框架,适合手机端访问。 首发版本&#x…...

如何做好一个决策:基于 Excel的决策树+敏感性分析应用(针对多个变量)
本文是对《如何做好一个决策:基于 Excel的决策树+敏感性分析应用》一文的补充。 示例背景 决策问题:是否开发新产品? 关键变量: 开发成本(B2):$500K, $700K, $1M高需求概率(B4):30%, 50%, 70%高需求收入(C4...

Azure DevOps 管道部署系列之一本地服务器
Azure DevOps 是一个帮助改进 SDLC(软件开发生命周期)的平台。 在本文中,我们将使用 Azure Pipelines 创建自动化部署。 Azure DevOps 团队将 Azure Pipelines 定义为“使用 CI/CD 构建、测试和部署,适用于任何语言、平台和云平台”。 在这里,我将解释如何在 Azure Dev…...
DeepSeekMath:突破开放式语言模型中数学推理能力的极限
摘要 由于数学推理具有复杂且结构化的特性,这对语言模型构成了重大挑战。在本文中,我们介绍了 DeepSeekMath 7B 模型,该模型在 DeepSeek-Coder-Base-v1.5 7B 模型的基础上,使用从 Common Crawl 获取的 1200 亿个与数学相关的标记,以及自然语言和代码数据继续进行预训练。…...
QT 5.15.2 程序中文乱码
1. 在.pro文件中添加: msvc { QMAKE_CXXFLAGS /source-charset:utf-8 /execution-charset:utf-8 }备注:.pro文件只有在选择 qmake 方式才会生成。 [Cmake 只会生成 CMakeLists.txt 文件] 2. 在文件首部增加以下程序行 #pragma execution_character_s…...

Celery简介
一、什么是异步任务队列 异步任务队列是指一种用于管理和调度异步执行任务的机制。具体来说,它允许将任务放入队列中,然后由后台进程异步处理这些任务,而不会阻塞主线程的执行。这种设计使得系统能够高效地处理耗时操作,同时保持…...
StarRocks物化视图
## 引言 在大数据时代,企业对实时数据分析的需求日益增长,而传统OLAP系统在处理复杂查询时往往面临性能瓶颈。StarRocks作为新一代极速全场景MPP分析型数据库,通过其独特的**物化视图(Materialized View, MV)**技术&a…...
vue2源码解析——响应式原理
文章目录 引言数据劫持收集依赖数组处理渲染watchervue3中的响应式 引言 vue的设计思想是数据双向绑定、数据与UI自动同步,即数据驱动视图。 为什么会这样呢?这就不得不提vue的响应式原理了,在使用vue的过程中,我被vue的响应式设…...

基于 GitLab CI + Inno Setup 实现 Windows 程序自动化打包发布方案
在 Windows 桌面应用开发中,实现自动化构建与打包发布是一项非常实用的工程实践。本文以我在开发PackTes项目时的为例,介绍如何通过 GitLab CI 配合 Inno Setup、批处理脚本、Qt 构建工具,实现版本化打包并发布到共享目录的完整流程。 项目地…...
做好 4个基本动作,拦住性能优化改坏原功能的bug
缺陷分析 “小李,202504300989这个现场缺陷你负责测试漏测分析,要求用5why方法找到漏测根因,根据找到的根因制定改进措施。你今天下班前完成,完成后立刻通知我,质量部现在每天都在催现场缺陷分析结果。”周二刚上班&a…...
【HarmonyOS 5】针对 Harmony-Cordova 性能优化,涵盖原生插件开发、线程管理和资源加载等关键场景
1. 原生图片处理插件(Java) package com.example.plugin; import ohos.media.image.ImageSource; import ohos.media.image.PixelMap; import ohos.app.Context; public class ImageProcessor { private final Context context; public ImagePro…...
零基础认知企业级数据分析平台如何落实数据建模(GAI)
理解数据建模的基本概念 数据建模是将业务需求转化为数据结构和关系的过程,核心目标是构建可支撑分析、预测或决策的数据模型。零基础需从以下维度入手: 业务理解:明确业务问题(如销售预测、用户分群),与…...

web架构2------(nginx多站点配置,include配置文件,日志,basic认证,ssl认证)
一.前言 前面我们介绍了一下nginx的安装和基础配置,今天继续来深入讲解一下nginx的其他配置 二.nginx多站点配置 一个nginx上可以运行多个网站。有多种方式: http:// ip/域名 端口 URI 其中,ip/域名变了,那么网站入口就变了…...

AI 的早期萌芽?用 Swift 演绎约翰·康威的「生命游戏」
文章目录 摘要描述题解答案题解代码分析示例测试及结果时间复杂度空间复杂度总结 摘要 你有没有想过,能不能通过简单的规则模拟出生与死亡?「生命游戏」正是这样一种充满魅力的数学模拟系统。这篇文章我们来聊聊它的规则到底有多神奇,并用 S…...
【DBA】MySQL经典250题,改自OCP英文题库中文版(2025完整版)
【DBA】MySQL经典250题,改自OCP英文题库中文版(2025完整版) ——2025.5.15 文章目录 P1:1-50(划重点)P2:51-100(划重点)P3:101-150(划重点打标记&…...
Cursor 编辑器介绍:专为程序员打造的 AI 编程 IDE
在现代软件开发中,AI 辅助编程正逐步改变开发者的工作方式。Cursor 正是这场变革中的佼佼者,它不仅是一个现代化的代码编辑器,更是将强大的 AI 编程助手深度集成到 IDE 的一次探索性尝试。 一、什么是 Cursor? Cursor 是一款基于…...

go|channel源码分析
文章目录 channelhchanmakechanchansendchanrecvcomplieclosechan channel 先看一下源码中的说明 At least one of c.sendq and c.recvq is empty, except for the case of an unbuffered channel with a single goroutine blocked on it for both sending and receiving usin…...