游乐游手机版
首页/AI教程/文章详情

Go语言求解树上勾股距离节点方法详解

时间:2026-06-06 16:54
2026-05-28:今天来聊一道有趣的树上算法题。给定一棵无向树(n 个节点,n-1 条边)和三个互不相同的目标节点 x、y、z,需要统计树上所有“特殊节点”的数量——所谓特殊节点,就是指它到 x、y、z 的三个距离,从小到大排序后满足勾股定理 a² + b² = c²。题目来自力扣 3820,数

2026-05-28:今天来聊一道有趣的树上算法题。给定一棵无向树(n 个节点,n-1 条边)和三个互不相同的目标节点 x、y、z,需要统计树上所有“特殊节点”的数量——所谓特殊节点,就是指它到 x、y、z 的三个距离,从小到大排序后满足勾股定理 a² + b² = c²。题目来自力扣 3820,数据规模 n 最大 10 万,采用线性时间算法即可高效求解。

树上勾股距离节点解题步骤详解

第一步:构建无向树的邻接表存储结构

树是由节点和边构成的无环连通图。要高效处理它,首先需要将输入的边信息转换为计算机能快速遍历的邻接表存储结构。

  1. 已知共有 n 个节点(编号 0 到 n-1),先创建一个长度为 n 的列表,每个位置对应一个节点,用于存储它的所有邻居。
  2. 遍历输入的 n-1 条边,每一条边连接两个节点 v 和 w:将 w 添加到 v 的邻居列表中,同时将 v 添加到 w 的邻居列表中——因为树是无向的,边是双向的。
  3. 构建完成后,后续所有距离计算均基于该邻接表进行。

第二步:实现「单源最短距离计算」功能

树的独特性质使得距离计算变得简单——任意两点之间仅有一条唯一路径,因此从起点出发,通过一次深度优先搜索(DFS)即可计算出所有节点的距离。

  1. 创建一个长度为 n 的距离数组,初始值全为 0(下标对应节点编号,值对应距离)。
  2. 从起点开始进行深度优先遍历(DFS),规则非常清晰:
    • 记录当前节点及其父节点(防止回溯);
    • 遍历当前节点的所有邻居,跳过父节点;
    • 邻居节点的距离 = 当前节点距离 + 1;
    • 递归继续遍历该邻居节点。
  3. 遍历结束后,距离数组存储了起点到每个节点的最短距离。

第三步:分别计算三个目标节点到全节点的距离

题目给出了三个固定节点 x、y、z,需要分别以它们为起点,调用第二步的函数,得到三组距离数据:

  1. 以 x 为起点,得到数组 dx:dx[i] 表示节点 i 到 x 的距离;
  2. 以 y 为起点,得到 dy;
  3. 以 z 为起点,得到 dz。

这样每个节点都对应三个距离值,便于后续判断。

第四步:遍历所有节点,判断是否为「特殊节点」

逐一检查树上的每个节点 i(从 0 到 n-1),判断规则严格遵循题目要求:

  1. 取出节点 i 的三个距离:dx[i]、dy[i]、dz[i];
  2. 对这三个数从小到大排序,得到 a、b、c(a ≤ b ≤ c);
  3. 验证勾股定理:a² + b² 是否等于 c²;
  4. 若成立则计数加 1,否则跳过。

第五步:返回最终统计结果

遍历完所有节点后,统计得到的数量即为答案。

时间复杂度分析

拆解每一步的复杂度(n 为节点总数):

  1. 构建邻接表:遍历 n-1 条边,时间复杂度为 O(n);
  2. 三次距离计算:每次 DFS 访问所有节点和边,单次 O(n),三次总计 O(3n) = O(n);
  3. 节点判断与计数:遍历 n 个节点,每个节点进行常数时间的排序(3 个数排序为 O(1))和公式验证,总耗时 O(n)。

总时间复杂度:O(n)(线性时间,应对 10 万级别数据毫无压力)

空间复杂度分析

评估额外占用的空间:

  1. 邻接表:存储 n 个节点和 n-1 条边,空间为 O(n);
  2. 距离数组:三个长度为 n 的数组,空间为 O(3n) = O(n);
  3. DFS 递归栈:最坏情况树呈链状,深度为 n,栈空间 O(n);
  4. 其他变量(计数、临时数组)均为常数空间 O(1)。

总空间复杂度:O(n),内存友好。

总结

  1. 核心流程:建邻接表 → 三次 DFS 计算距离 → 遍历节点验证勾股定理 → 统计结果;
  2. 时间复杂度:O(n)(线性时间,高效处理十万级节点);
  3. 空间复杂度:O(n)(线性空间,满足题目内存要求)。

Go 完整代码如下:

package main

import (
    "fmt"
    "slices"
)

func specialNodes(n int, edges [][]int, x, y, z int) (ans int) {
    g := make([][]int, n)
    for _, e := range edges {
        v, w := e[0], e[1]
        g[v] = append(g[v], w)
        g[w] = append(g[w], v)
    }

    calcDis := func(start int) []int {
        dis := make([]int, n)
        var dfs func(int, int)
        dfs = func(v, fa int) {
            for _, w := range g[v] {
                if w != fa {
                    dis[w] = dis[v] + 1
                    dfs(w, v)
                }
            }
        }
        dfs(start, -1)
        return dis
    }

    dx := calcDis(x)
    dy := calcDis(y)
    dz := calcDis(z)

    for i := range n {
        a := []int{dx[i], dy[i], dz[i]}
        slices.Sort(a)
        if a[0]*a[0]+a[1]*a[1] == a[2]*a[2] {
            ans++
        }
    }

    return
}

func main() {
    n := 4
    edges := [][]int{{0, 1}, {0, 2}, {0, 3}}
    x := 1
    y := 2
    z := 3
    result := specialNodes(n, edges, x, y, z)
    fmt.Println(result)
}

Python 完整代码如下:

# -*-coding:utf-8-*-
from typing import List

def specialNodes(n: int, edges: List[List[int]], x: int, y: int, z: int) -> int:
    # 构建邻接表
    g = [[] for _ in range(n)]
    for v, w in edges:
        g[v].append(w)
        g[w].append(v)

    # 计算从 start 出发到所有节点的距离
    def calcDis(start: int) -> List[int]:
        dis = [0] * n
        visited = [False] * n

        def dfs(v: int):
            visited[v] = True
            for w in g[v]:
                if not visited[w]:
                    dis[w] = dis[v] + 1
                    dfs(w)

        dfs(start)
        return dis

    dx = calcDis(x)
    dy = calcDis(y)
    dz = calcDis(z)

    ans = 0
    for i in range(n):
        a = [dx[i], dy[i], dz[i]]
        a.sort()
        if a[0] * a[0] + a[1] * a[1] == a[2] * a[2]:
            ans += 1
    return ans

def main():
    n = 4
    edges = [[0, 1], [0, 2], [0, 3]]
    x = 1
    y = 2
    z = 3
    result = specialNodes(n, edges, x, y, z)
    print(result)

if __name__ == "__main__":
    main()

C++ 完整代码如下:

#include 
#include 
#include 
#include 

using namespace std;

int specialNodes(int n, vector>& edges, int x, int y, int z) {
    // 构建邻接表
    vector> g(n);
    for (auto& e : edges) {
        int v = e[0], w = e[1];
        g[v].push_back(w);
        g[w].push_back(v);
    }

    // 计算从 start 出发到所有节点的距离
    auto calcDis = [&](int start) -> vector {
        vector dis(n, 0);
        // DFS 函数声明
        function dfs = [&](int v, int fa) {
            for (int w : g[v]) {
                if (w != fa) {
                    dis[w] = dis[v] + 1;
                    dfs(w, v);
                }
            }
        };
        dfs(start, -1);
        return dis;
    };

    vector dx = calcDis(x);
    vector dy = calcDis(y);
    vector dz = calcDis(z);

    int ans = 0;
    for (int i = 0; i < n; i++) {
        vector a = {dx[i], dy[i], dz[i]};
        sort(a.begin(), a.end());
        if (a[0] * a[0] + a[1] * a[1] == a[2] * a[2]) {
            ans++;
        }
    }
    return ans;
}

int main() {
    int n = 4;
    vector> edges = {{0, 1}, {0, 2}, {0, 3}};
    int x = 1, y = 2, z = 3;
    int result = specialNodes(n, edges, x, y, z);
    cout << result << endl;
    return 0;
}

来源:https://bbs.huaweicloud.com/blogs/478274
上一篇AI系统架构设计原理与核心解析 下一篇2026最新OpenClaw小龙虾AI智能体零基础实操教程
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
MyShell发布开源AI语音克隆工具OpenVoice,瞄准语音模仿领域
AI教程 · 2026-07-14

MyShell发布开源AI语音克隆工具OpenVoice,瞄准语音模仿领域

MyShell最新推出的开源语音克隆工具OpenVoice引起了广泛关注。这一创新产品由麻省理工学院(MIT)、清华大学以及加拿大人工智能初创公司MyShell合作开发。OpenVoice采用了一种概念简单但高效的方法,可几乎即时克隆用户的语音,并使用明显更少的计算资源。该工具不仅具备语音克隆的基本

Open Voice:轻松克隆任何声音,免费开源的AI语音克隆项目
AI教程 · 2026-07-14

Open Voice:轻松克隆任何声音,免费开源的AI语音克隆项目

Open Voice是由MyShell推出的一个免费开源的AI即时语音克隆项目,相较于其他的语音克隆技术,OpenVoice的优势在于仅需一段简短的音频,便能以惊人的准确度复刻说话者的音色,创造出让人信以为真的自然语音。除开复制和参考说话者的音色之外,OpenVoice还可以对语音风格进行精细控制,

VoiceCanvas-AI语音克隆 & TTS工具 | 40+种语言语音合成
AI教程 · 2026-07-14

VoiceCanvas-AI语音克隆 & TTS工具 | 40+种语言语音合成

VoiceCanvas是什么?VoiceCanvas是由先进AI驱动的语音克隆与文本转语音工具,支持40+种语言的即时语音合成。其核心能力包括:高质量语音合成:具有自然语调和节奏的清晰人声个性化语音克隆:通过3-10秒语音样本创建专属AI声纹多语言支持:覆盖全球主流语种的男 女声选择进阶调控功能:语

Github爆火AI语音克隆项目OpenVoice,精准进行声音复刻
AI教程 · 2026-07-14

Github爆火AI语音克隆项目OpenVoice,精准进行声音复刻

最近,Github上的一个名为OpenVoice的AI语音克隆项目爆火,该项目由myshell-ai开源,仅开源了不到三周,就有了6 1k的star。OpenVoice仅需参考说话者的短音频片段,即可复制其声音并生成多种语言的语音。这一技术不仅实现了对音色的准确克隆,还在语音生成过程中提供了对情感、

Free Voice Cloning-免费AI语音克隆工具 | 5秒生成你的数字声音
AI教程 · 2026-07-14

Free Voice Cloning-免费AI语音克隆工具 | 5秒生成你的数字声音

Free Voice Cloning,一款真正0成本、无限制、跨语言的高质量AI语音克隆平台。适合内容创作者、教育者、AI开发者、播客人群等所有想要“复制自己的声音”并进行语音合成的用户。?️ Free Voice Cloning 是什么?Free Voice Cloning 是一个基于先进AI语音