You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非二叉树中最近公共管理者(LCM)代码问题修复求助

非二叉树最近公共管理者(LCM)修复方案

问题背景

我需要在非二叉树中找到两个节点的最近公共管理者(LCM),用二叉树做简化演示:

  • 传入节点H和I时,正确返回E;
  • 传入节点D和I时,正确返回B。
    当前代码多数情况正常,但传入节点I和L时,代码返回I,而我预期返回E,该如何修复?

原代码

class Node
{
    public string Name { get; set; }
    public List<Node> Children { get; set; }
    public Node(string name)
    {
        Name = name;
        Children = new List<Node>();
    }
}
class CommonManager
{
    public static Dictionary<string, Node> dictionary;

    public CommonManager()
    {
        dictionary = new Dictionary<string, Node>();
        Node root = new Node("A");
        root.Children.Add(new Node("B"));
        //root.Children.Add(new Node("C"));
        //root.Children.Add(new Node("AA"));
        root.Children[0].Children.Add(new Node("D"));
        root.Children[0].Children.Add(new Node("E"));
        //root.Children[1].Children.Add(new Node("F"));
        //root.Children[1].Children.Add(new Node("G"));
        root.Children[0].Children[1].Children.Add(new Node("H"));
        root.Children[0].Children[1].Children.Add(new Node("I"));
        //root.Children[1].Children[0].Children.Add(new Node("J"));
        //root.Children[1].Children[0].Children.Add(new Node("K"));
        root.Children[0].Children[1].Children[1].Children.Add(new Node("L"));

        Node n1 = root.Children[0].Children[1].Children[1].Children[0];//L
        Node n2 = root.Children[0].Children[1].Children[1];//I

        Node lcm = FindLCM(root, n1, n2);
        if (lcm != null)
            Console.WriteLine("The LCM is " + lcm.Name);
        else
            Console.WriteLine("No LCM found.");

        Console.ReadKey();
    }

    static Node FindLCM(Node root, Node n1, Node n2)
    {
        if (root == null)
            return null;

        //If selected node is n1 or n2 return node. 
        if (root == n1 || root == n2)
            return root;

        Node lcm = null;
        int count = 0;
        //Use debug > Windows > Parallel Watch to track variables. 
        foreach (Node child in root.Children)
        {
            Console.WriteLine(child.Name);
            Node temp = FindLCM(child, n1, n2);
            if (temp != null)
            {
                lcm = temp;
                Console.WriteLine("temp.Name:--> " + temp.Name);
                count++;
            }
        }

        if (count == 2)
            return root;
        else
            return lcm;
    }
}

问题原因

按常规LCM定义,I是L的直接父节点,I和L的最近公共管理者就是I,代码返回的结果是正确的。如果你确实需要返回E,说明你的需求是LCM不能是目标节点本身,必须是两个节点的上层公共祖先。

当前代码的逻辑漏洞在于:当遍历到目标节点(比如I)时,会直接返回该节点,不会继续遍历它的子节点,因此无法发现该节点的子树中存在另一个目标节点(L)。此时count始终为1,最终返回的是先匹配到的目标节点,而非你预期的上层祖先。

修复方案

修改递归逻辑,不直接返回目标节点,而是先遍历所有子节点,统计子树中包含目标节点的数量,再结合当前节点是否为目标节点来判断:

static Node FindLCM(Node root, Node n1, Node n2)
{
    if (root == null)
        return null;

    int count = 0;
    Node result = null;

    // 先遍历所有子节点,收集子树中的匹配情况
    foreach (Node child in root.Children)
    {
        Node temp = FindLCM(child, n1, n2);
        if (temp != null)
        {
            count++;
            result = temp;
        }
    }

    // 判断当前节点是否是目标节点之一
    bool isTarget = root == n1 || root == n2;
    if (isTarget)
    {
        count++;
    }

    // 两种情况返回当前节点:
    // 1. 当前节点是目标节点,且子树中存在另一个目标节点(count=2)
    // 2. 子树中有两个不同的目标节点(count=2)
    if (count == 2)
    {
        return root;
    }

    // 如果当前节点是目标节点,返回自己;否则返回子树中的匹配结果
    return isTarget ? root : result;
}

修复后逻辑说明

  • 遍历所有子节点,统计子树中包含目标节点的数量;
  • 若当前节点是目标节点,计数加1;
  • 当计数为2时,说明当前节点就是两个目标节点的最近公共管理者(不管当前节点是否是目标节点);
  • 若当前节点是目标节点且计数为1,返回当前节点(符合常规LCM定义);若需要强制排除自身作为LCM,可在此处调整逻辑(比如返回null,让上层节点继续判断)。

如果你的需求确实是LCM不能是目标节点本身,可以进一步修改:当当前节点是目标节点且计数为1时,返回null,这样上层节点会捕获到子树中存在目标节点,最终返回上层的公共祖先。修改后的对应代码段:

// 如果当前节点是目标节点,返回null(让上层节点处理);否则返回子树中的匹配结果
return isTarget ? null : result;

内容的提问来源于stack exchange,提问作者OpenStack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 20:15:55