当前位置: 首页 > news >正文

千问 LeetCode 2973. 树中每个节点放置的金币数目 Go实现

以下是 LeetCode 2973. 树中每个放置的金币数目 的 Go 语言实现:

package main

import (
"sort"
)

func placedCoins(edges [][]int, cost []int) []int64 {
n := len(cost)
// 1. 建图 (邻接表)
g := make([][]int, n)
for _, edge := range edges {
u, v := edge[0], edge[1]
g[u] = append(g[u], v)
g[v] = append(g[v], u)
}

ans := make([]int64, n)
// 默认每个节点初始金币数为 1
for i := range ans {
ans[i] = 1
}

// 2. 深度优先搜索
var dfs func(node, fa int) []int
dfs = func(node, fa int) []int {
// 收集当前子树的节点索引
subtree := []int{node}

for _, neighbor := range g[node] {
if neighbor == fa {
continue // 无向树深搜防环,跳过父节点
}
sub := dfs(neighbor, node)
if len(sub) < 5 {
subtree = append(subtree, sub...)
} else {
// 只保留2个最小的和3个最大的
subtree = append(subtree, sub[0], sub[1], sub[len(sub)-3], sub[len(sub)-2], sub[len(sub)-1])
}
}

// 对当前子树的候选节点按 cost 排序
sort.Slice(subtree, func(i, j int) bool {
return cost[subtree[i]] < cost[subtree[j]]
})

// 如果节点数大于5,只保留极值
if len(subtree) > 5 {
subtree = []int{
subtree[0], subtree[1],
subtree[len(subtree)-3], subtree[len(subtree)-2], subtree[len(subtree)-1],
}
}

// 计算当前节点应放置的金币数
if len(subtree) >= 3 {
sz := len(subtree)
// 组合1: 两个最小的负数 * 最大的正数
prod1 := int64(cost[subtree[0]]) * int64(cost[subtree[1]]) * int64(cost[subtree[sz-1]])
// 组合2: 三个最大的正数
prod2 := int64(cost[subtree[sz-3]]) * int64(cost[subtree[sz-2]]) * int64(cost[subtree[sz-1]])

maxProd := prod1
if prod2 > maxProd {
maxProd = prod2
}

if maxProd > 0 {
ans[node] = maxProd
} else {
ans[node] = 0
}
}

return subtree
}

dfs(0, -1)
return ans
}

核心逻辑与 Go 语言特性说明:
1. 闭包与状态传递:在 Go 中,我们使用匿名函数 dfs 作为闭包,这样可以直接访问外部的 cost 数组和 ans 结果数组,避免了在函数参数中反复传递这些大数组,代码更加简洁。
2. 数学规律:要在一个包含正负数的数组中选出3个数使乘积最大,只有两种可能:
- 三个最大的正数
- 一个最大的正数和两个最小的负数
3. 剪枝优化:基于上述规律,我们在深度优先搜索(DFS)合并子树时,不需要保留所有的节点。每个子树最多只需要保留 2个最小的 和 3个最大的 节点(共5个)即可。这大幅降低了存储和排序的复杂度,使得时间复杂度维持在 O(N log N) 级别。
4. 防环处理:由于是无向树,DFS 时需要传入父节点 fa,遇到父节点直接跳过,防止走回头路形成死循环。
5. 结果计算:当子树节点数不足3个时,金币数保持初始值1;当大于等于3个时,取上述两种组合乘积的最大值,若为负数则放置0个金币。注意 Go 中 int 的乘法可能会溢出,计算乘积时使用了 int64 进行强转。

http://www.jsqmd.com/news/964682/

相关文章:

  • 别再为版本头疼了!手把手教你让CarSim 2020.0和MATLAB R2015a/R2016b成功‘牵手’
  • 2026 北京旅游避坑指南:5 家靠谱地接机构实测对比 - 互联网科技品牌测评
  • 上海交大谢伟迪团队借助Codex打造全球首个大规模标准化病人AI评估基准,给7款主流大模型来了一场临床执业医师考试
  • 分布式强一致性防线:深入 Raft 协议脑裂(Split-brain)场景的 Leader 选举与多版本并发控制(MVCC)数据修复
  • 前端新手福音:在快马平台用一句话生成你的第一个加载动画代码
  • ai辅助开发:借助快马平台智能生成win11开始菜单自定义设置工具
  • 大模型流式响应稳定性治理:用 Go 构建防超时与连接泄漏的 SSE 管道
  • FPGA数字电路设计入门:从Verilog到硬件调试的完整实践指南
  • 2026年杭州公考/考公/公务员/省考/事业编/事业单位培训机构推荐榜单:专业师资与上岸率口碑之选 - 企业推荐官【官方】
  • 数据自主权实践:开源工具实现微信聊天记录永久保存与智能分析
  • 数学艺术图案画-曼陀罗(25)
  • 终极Android Root解决方案:Magisk系统级定制完全指南
  • AI 数字人直播系统深度测评:中小商家 7×24 小时直播的降本增效神器
  • 嵌入式Day25--多任务并发
  • 效率直接起飞 AI论文写作软件测评:2026年最新推荐与对比
  • Wyze摄像头安装螺丝有误致电池过热,13起报告6起爆炸起火,公司提供退款或换品
  • 2026年小苏打厂家推荐:食品级/工业级小苏打源头企业,高纯度与环保生产工艺深度解析 - 品牌企业推荐师(官方)
  • 为什么多算一次反而更快?深入 Blackwell 微架构,拆解 FlashAttention-4 的逆天优化
  • 高光谱遥感之光谱重建
  • 到底为什么PHP要有RESTful?
  • KEDA 事件驱动弹性伸缩实战:从消息队列到工作流编排的完整落地
  • Nios II开发全流程疑难杂症排查指南:从硬件设计到软件调试
  • 成都水处理设备厂家怎么选?2026本地靠谱企业盘点及选购指南 - 新闻快传
  • 实战指南:基于快马AI在CentOS7上一键部署企业级GitLab服务器
  • AI 数字人直播系统实测:零门槛操作如何让小白 15分钟上手直播?
  • Django动态权限拦截器——自定义 Middleware 实现全局鉴权与黑白名单
  • 3步彻底解决Flow Launcher搜索失效:Everything服务修复终极指南
  • 开发提效神器:用快马AI一键生成阿里云盘核心上传与秒传代码
  • 如何用Rust构建高效小说下载器:Tomato-Novel-Downloader技术深度解析
  • 终极指南:使用bandcamp-dl高效下载Bandcamp音乐