讲师中心 微信公众号
AI工具推荐 视频效率加速

LeetCode 2467 题解:树中最高盈利路径的正确 BFS 层序遍历实现

夜强君_6023

夜强君_6023

发布时间:2026-09-02 13:16:07

|

166人浏览过

|

来源于php中文网

原创

LeetCode 2467 题解:树中最高盈利路径的正确 BFS 层序遍历实现

本文详解 leetcode 2467「树中最高盈利路径」的算法逻辑,并重点指出 javascript 实现中因动态数组长度判断导致的层序遍历错误,提供修复方案与完整可运行代码。

本文详解 leetcode 2467「树中最高盈利路径」的算法逻辑,并重点指出 javascript 实现中因动态数组长度判断导致的层序遍历错误,提供修复方案与完整可运行代码。

LeetCode 2467 要求在无向树中模拟 Alice 从节点 0 出发、Bob 从给定节点 bob 出发同时向根节点 0 移动的过程,计算 Alice 沿任意根到叶路径所能获得的最大净收益。关键约束在于:若 Alice 与 Bob 同时到达同一节点,该节点金额减半;若 Bob 先到达(即更早抵达),Alice 到达时收益为 0;否则 Alice 获得全额金额。

算法分为两步:

  1. 预处理 Bob 的路径:通过 DFS 找出 Bob 从起点到根节点 0 的唯一路径,并记录每个节点在该路径中的到达步数(深度),存入哈希表 step;
  2. BFS 模拟 Alice 的所有可能路径:从节点 0 开始层序遍历,对每个扩展节点 neighbor,根据当前 depth + 1(Alice 到达该节点的步数)与 step[neighbor](Bob 到达该节点的步数)的关系,决定收益:
    • depth + 1 或 <code>neighbor 不在 Bob 路径中 → 全额 amount[neighbor];
    • depth + 1 === step[neighbor] → 半额 Math.floor(amount[neighbor] / 2);
    • depth + 1 > step[neighbor] → 收益为 0。

⚠️ 关键陷阱(导致 JS 版本失败的根本原因):
Python 原版使用 for _ in range(len(que)) 固定遍历当前层节点数,而原始 JS 代码写成:

for (let j = 0; j < queue.length; j++) {
    let [cur, parent, profit] = queue.shift();
    // ... 推入新节点 queue.push(...)
}

由于 queue.length 在每次循环条件判断时动态更新(shift() 减少、push() 增加),导致内层循环实际遍历的节点数远超预期,破坏了层序结构——Alice 的“深度”depth 不再准确对应其所在层级,进而使 depth + 1 与 step[neighbor] 的比较失效,最终低估收益(如失败用例中输出 16435,期望 17590)。

✅ 正确修复方式:在循环开始前缓存当前层节点数量:

const levelSize = queue.length;
for (let j = 0; j < levelSize; j++) {
    let [cur, parent, profit] = queue.shift();
    // ... 正常处理,queue.push() 不影响本次循环次数
}

或使用倒序计数(更简洁):

for (let j = queue.length; j > 0; j--) {
    let [cur, parent, profit] = queue.shift();
    // ...
}

以下是修复后的完整 JavaScript 解决方案(已通过全部测试用例,包括问题中提供的失败用例):

/**
 * @param {number[][]} edges
 * @param {number} bob
 * @param {number[]} amount
 * @return {number}
 */
var mostProfitablePath = function(edges, bob, amount) {
    const n = amount.length;
    const graph = Array.from({ length: n }, () => []);

    for (const [u, v] of edges) {
        graph[u].push(v);
        graph[v].push(u);
    }

    // DFS to find Bob's path to node 0
    let bobPath = null;
    const dfs = (node, parent, path) => {
        if (node === 0) {
            bobPath = [...path];
            return true;
        }
        for (const neighbor of graph[node]) {
            if (neighbor === parent) continue;
            path.push(neighbor);
            if (dfs(neighbor, node, path)) return true;
            path.pop();
        }
        return false;
    };
    dfs(bob, -1, [bob]);

    // Map: node -> Bob's arrival step
    const step = {};
    for (let i = 0; i < bobPath.length; i++) {
        step[bobPath[i]] = i;
    }

    // BFS for Alice starting from node 0
    let ans = -Infinity;
    const iniProfit = (bob === 0) ? Math.floor(amount[0] / 2) : amount[0];
    let queue = [[0, -1, iniProfit]]; // [node, parent, profit]
    let depth = 0;

    while (queue.length > 0) {
        const levelSize = queue.length; // ✅ Critical fix: freeze current level size
        for (let j = 0; j < levelSize; j++) {
            const [cur, parent, profit] = queue.shift();

            // Leaf node (except root): update answer
            if (cur !== 0 && graph[cur].length === 1) {
                ans = Math.max(ans, profit);
            }

            // Explore neighbors
            for (const neighbor of graph[cur]) {
                if (neighbor === parent) continue;

                let newProfit;
                if (!step.hasOwnProperty(neighbor) || depth + 1 < step[neighbor]) {
                    newProfit = amount[neighbor];
                } else if (depth + 1 === step[neighbor]) {
                    newProfit = Math.floor(amount[neighbor] / 2);
                } else {
                    newProfit = 0;
                }
                queue.push([neighbor, cur, profit + newProfit]);
            }
        }
        depth++;
    }

    return ans;
};

? 补充说明:

  • Bob 的 DFS 必须保证找到唯一最短路径(树中两点间路径唯一),因此无需额外剪枝;
  • Alice 的 BFS 使用 graph[cur].length === 1 && cur !== 0 判断叶子节点是安全的(根节点 0 度数可能为 1,但非叶子);
  • 整数除法统一使用 Math.floor(x / 2),确保负数(如 -9152)也向下取整,符合题意(如 -9152 / 2 = -4576);
  • 时间复杂度:O(n),空间复杂度:O(n),满足大规模输入要求。

掌握层序遍历中“冻结队列长度”这一细节,是避免 BFS 类题目逻辑错误的关键。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

相关专题

更多
PHP2Shell高危漏洞修复教程
PHP2Shell高危漏洞修复教程

PHP2Shell漏洞是什么,哪些PHP版本和运行环境会受到影响,服务器应该如何检测与修复?本专题提供版本自查脚本、Linux与Docker升级命令、PHP-FPM和Apache排查步骤,以及修复验证、临时缓解和应急响应方案。

0

2026.10.22

剧云人物设定与关系管理教程
剧云人物设定与关系管理教程

本专题介绍剧云人物设定与关系管理,讲解角色小传、性格职业、人物目标、背景资料和关系网络的创建及维护方法。

0

2026.10.22

剧云故事大纲与分场规划教程
剧云故事大纲与分场规划教程

本专题讲解剧云梗概与多级大纲功能,覆盖全局、分集、分场结构生成,以及主线冲突、剧情节点和场次顺序调整。

0

2026.10.22

VibeKnow PPT讲解视频教程汇总
VibeKnow PPT讲解视频教程汇总

本专题介绍VibeKnow PPT讲解模式的素材准备、旁白生成、页面节奏、画面呈现与导出设置,适合课程和培训场景。

0

2026.10.22

VibeKnow PDF转视频教程合集
VibeKnow PDF转视频教程合集

本专题围绕VibeKnow的PDF转视频功能,讲解文件准备、内容解析、脚本生成、重点可视化及配音字幕检查方法。

0

2026.10.22

二狗PPT模板与视觉设计
二狗PPT模板与视觉设计

本专题介绍二狗PPT的职场模板、主题风格与页面版式,覆盖模板切换、色彩选择、内容匹配和正式汇报场景下的视觉优化方法。

0

2026.10.22

php漏洞修复方法
php漏洞修复方法

PHP漏洞聚合专题,持续整理PHP最新高危漏洞、CVE安全预警、受影响版本、自查命令及修复方案,覆盖PHP-FPM、Docker、Ubuntu与Linux服务器环境,帮助开发者快速完成漏洞排查、版本升级和安全加固。

20

2026.10.22

二狗PPT入门与基础操作
二狗PPT入门与基础操作

本专题整理二狗PPT从官网进入、输入主题、生成大纲到制作成稿的基础操作,帮助新手掌握AI一键生成职场PPT的完整流程。

0

2026.10.22

讯飞绘文AI配图与绘图模型合集
讯飞绘文AI配图与绘图模型合集

本专题讲解讯飞绘文AI配图与绘图2.0 Pro,覆盖提示词、画面比例、参考图、风格选择及图片优化,帮助用户制作匹配内容的视觉素材。

0

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn