Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 返回层次结构中的Boss--尝试应用深度优先搜索_C#_Algorithm_Data Structures_Graph_Depth First Search - Fatal编程技术网

C# 返回层次结构中的Boss--尝试应用深度优先搜索

C# 返回层次结构中的Boss--尝试应用深度优先搜索,c#,algorithm,data-structures,graph,depth-first-search,C#,Algorithm,Data Structures,Graph,Depth First Search,XYZ是一家拥有首席执行官比尔和一系列员工的公司。员工可以有一个向他们报告的其他员工的列表,这些员工自己也可以有报告,等等。至少有一份报告的员工称为经理。 请使用ClosesCommonManager方法查找离两名员工最近的经理(即离CEO最远的经理)。您可以假设所有员工最终都向首席执行官报告 样本数据: 首席执行官比尔有3名员工向他汇报:{Dom,Samir,Michael} 多姆有三份报告{彼得、鲍勃、波特} 萨米尔没有报告{}迈克尔没有报告{} 彼得有两份报告{米尔顿,尼娜}鲍勃没有报告{

XYZ是一家拥有首席执行官比尔和一系列员工的公司。员工可以有一个向他们报告的其他员工的列表,这些员工自己也可以有报告,等等。至少有一份报告的员工称为经理。 请使用ClosesCommonManager方法查找离两名员工最近的经理(即离CEO最远的经理)。您可以假设所有员工最终都向首席执行官报告

样本数据: 首席执行官比尔有3名员工向他汇报:{Dom,Samir,Michael}

多姆有三份报告{彼得、鲍勃、波特}

萨米尔没有报告{}迈克尔没有报告{}

彼得有两份报告{米尔顿,尼娜}鲍勃没有报告{}

波特没有报告米尔顿没有报告

尼娜没有报告{}

电话样本: 密室经理(米尔顿,尼娜)=彼得

ClosesCommonManager(尼娜,波特)=Dom

closestCommonManager(尼娜,萨米尔)=比尔

密室经理(彼得,尼娜)=彼得

现在,为了解决这个问题,我已经这样做了——但我还没有找到解决办法。 我曾尝试使用简单的DFS算法,但无法完成解决方案

    public static Employee closestCommonManager(Employee ceo, Employee firstEmployee, Employee secondEmployee)
    {
        var visited = new HashSet<Employee>();
        bool firstFound = false, secondFound = false;

        Stack<Employee> stack = new Stack<Employee>(); // DFS
        stack.Push(ceo);

        while (stack.Count != 0)
        {
            Employee current = stack.Pop();
            IList<Employee> employeeList = current.getReports();

            if (firstEmployee.getId() == current.getId())
            {
                firstFound = true;
            }
            else if (secondEmployee.getId() == current.getId())
            {
                secondFound = true;
            }

            if (firstFound && secondFound)
                return current;
            // Should i return previous one? how do i keep track of the
            // node which i found first in hierarchy ???


            Console.WriteLine(current.getName());

            foreach (var employee in employeeList)
            {
                if (visited.Add(employee))
                {
                    stack.Push(employee);
                }
            }
        }

        return null;
    }
public static Employee closestCommonManager(员工ceo、员工第一名员工、员工第二名员工)
{
var=newhashset();
bool firstFound=false,secondFound=false;
堆栈=新堆栈();//DFS
stack.Push(首席执行官);
while(stack.Count!=0)
{
员工当前=stack.Pop();
IList employeeList=current.getReports();
if(firstEmployee.getId()==current.getId())
{
firstFound=true;
}
else if(secondEmployee.getId()==current.getId())
{
secondFound=true;
}
如果(第一次发现和第二次发现)
回流;
//我应该返回上一个吗?我如何跟踪
//我在层次结构中首先找到的节点???
Console.WriteLine(current.getName());
foreach(员工列表中的var员工)
{
如果(已访问。添加(员工))
{
stack.Push(员工);
}
}
}
返回null;
}

在这个解决方案中,我向员工添加了两个字段:

//all managers of this Employee
public List<Employee> Bosses = new List<Employee>();
//how many managers between employee and Ceo
public int DistanceFromCeo = 0;
现在很容易找到答案-加入老板,找到最遥远的人:

var commonBosses = (from f in firstEmployee.Bosses
    join s in firstEmployee.Bosses on f.getId() equals s.getId()
    select f).ToList();
var maxLenght = commonBosses.Max(b => b.DistanceFromCeo);

return commonBosses.FirstOrDefault(b => b.DistanceFromCeo == maxLenght);

只有在层次结构中没有循环时,它才会工作。但是我想如果有循环,那么谁是最远的还不清楚,如果你在循环中运行,状态将无限增长。

这看起来像是一个请求。聪明的算法通常会对树进行一些预处理。一种简单的方法是标记树中每个元素与根的距离。然后,要找到两个节点最接近的共同祖先,首先从较低的节点向上移动一个指针,使它们位于相同的深度,然后将两个指针一起向上移动,直到指针接触。如果不进行预处理,可以同时从两个节点向上移动,将看到的所有节点添加到一个集合中,并检查何时将节点添加到已经存在的节点集合中。在任何一种情况下,当您第一次遇到来自两侧的节点时,该节点是最低的共同祖先。

DFS的简单解决方案

单独的任务
创建DFS函数以查找从根目录到辅助目录的路径。(列表或堆栈)
为两个工作进程调用它,然后比较从根到工作进程的路径

最后一场比赛是你的目标

这是我的解决方案,但由于某些原因,它没有被接受:

 public static Employee ret;
    public static bool first = false;
    public static bool second = false;
    public static Employee closestCommonManager(Employee ceo, Employee firstEmployee, Employee secondEmployee)
    {
        // Implement me                                                
        if (ceo == null || firstEmployee == null || secondEmployee == null)
            return null;
        if (ceo.getId() == firstEmployee.getId())
            first = true;
        if (ceo.getId() == secondEmployee.getId())
            second = true;
        if (first && second)
            return ceo;
        else
        {
            foreach (Employee e in ceo.getReports())
            {
                if (ret == null)
                {
                    var r = closestCommonManager(e, firstEmployee, secondEmployee);
                    if (r != null && ret == null)
                        ret = ceo;
                }
                else
                    return ret;
            }
        }
        return null;
    }
public static Employee closestCommonManager(Employee ceo, Employee firstEmployee, Employee secondEmployee)
{

    // Implement me
    var Manager = ceo.getReports();
    Employee tempEmployee = ceo;
    foreach (var HisReporter in Manager)
    {
        if (HisReporter.Equals(firstEmployee) || HisReporter.Equals(secondEmployee))
        {
            //if one of the employees are reporting to him return manager
            tempEmployee = ceo;
        }
        else if(HisReporter.getReports().Count > 0)
        {
            //if non of the employees reporting to him check if his reporters having these employees
            tempEmployee = closestCommonManager(HisReporter, firstEmployee, secondEmployee);
        }
    }
    return tempEmployee;
}

}以下是Krzysztof Bardzinski建议的DFS实现

 static void Main(string[] args)
    {
        Dictionary<int, Employee> employeeMap = new Dictionary<int, Employee>();
        Employee ceo = null, firstEmployee = null, secondEmployee = null;
        /*//Sample input
         List<string> input = new List<string>();
         input.Add("employee 1 A");
         input.Add("employee 2 B");
         input.Add("employee 3 C");
         input.Add("employee 4 D");
         input.Add("employee 5 E");
         input.Add("employee 6 F");
         input.Add("employee 7 G");
         input.Add("employee 8 H");
         input.Add("employee 9 I");
         input.Add("employee 10 J");
         input.Add("employee 11 K");
         input.Add("employee 12 L");
         input.Add("employee 13 M");

         input.Add("report 1 2");
         input.Add("report 1 3");

         input.Add("report 2 4");
         input.Add("report 2 5");
         input.Add("report 2 6");

         input.Add("report 5 7");
         input.Add("report 5 8");

         input.Add("report 6 9");
         input.Add("report 6 10");

         input.Add("report 3 11");
         input.Add("report 3 12");
         input.Add("report 3 13");

         input.Add("params 1 9 13");*/

        string line;
        while ((line = Console.ReadLine()) != null)
        {
            string[] tokens = line.Split();
            string type = tokens[0];

            if (type.Equals("employee"))
            {
                int id = int.Parse(tokens[1]);
                String name = tokens[2];
                employeeMap.Add(id, new Employee(id, name));
            }
            else if (type.Equals("report"))
            {
                Employee manager = employeeMap[int.Parse(tokens[1])];
                Employee report = employeeMap[int.Parse(tokens[2])];
                manager.addReport(report);
            }
            else if (type.Equals("params"))
            {
                ceo = employeeMap[int.Parse(tokens[1])];
                firstEmployee = employeeMap[int.Parse(tokens[2])];
                secondEmployee = employeeMap[int.Parse(tokens[3])];
            }
            else
            {
                // ignore comments and whitespace
            }
        }

        Employee result = closestCommonManager(ceo, firstEmployee, secondEmployee);
    } 
public static Employee closestCommonManager(Employee ceo, Employee firstEmployee, Employee secondEmployee)
    {
        Stack<Employee> firstManagers = new Stack<Employee>();
        Stack<Employee> secondManagers = new Stack<Employee>();
        if (ceo.getReports().Count > 0)
        {
            searchManager(ceo, firstEmployee, firstManagers);
            searchManager(ceo, secondEmployee, secondManagers);
            if (firstManagers.Contains(secondEmployee))
            {
                return secondEmployee; //closest manager as this is managing the first one
            }
            if (secondManagers.Contains(firstEmployee))
            {
                return firstEmployee; //closest manager as this is managing the second one
            }

            //check for closest match

            //make them equal in length.
            while (firstManagers.Count > secondManagers.Count)
            {
                firstManagers.Pop();
            }

            while (secondManagers.Count > firstManagers.Count)
            {
                secondManagers.Pop();
            }
            int checkCount = firstManagers.Count;
            for (int i = 0; i < checkCount; i++)
            {
                if (firstManagers.Peek().getId() == secondManagers.Peek().getId())
                {
                    return firstManagers.Pop();
                }
                else
                {
                    firstManagers.Pop();
                    secondManagers.Pop();
                }
            }
        }
        return null;
    }

    private static bool searchManager(Employee manager, Employee emp, Stack<Employee> graph)
    {
        bool res = false;
        graph.Push(manager);
        foreach (Employee e in manager.getReports())
        {
            if (e.getId() == emp.getId())
            {
                res = true;
                break;
            }
            else
            {
                if (e.getReports().Count > 0)
                {
                    if (searchManager(e, emp, graph))
                    {
                        return true;
                    }
                    else
                    {
                        graph.Pop();
                    }
                }
            }
        }
        return res;
    }

 public sealed class Employee
{

    private readonly int id;
    private readonly string name;
    private readonly List<Employee> reports;

    public Employee(int id, string name)
    {
        this.id = id;
        this.name = name;
        this.reports = new List<Employee>();
    }

    /// <returns> 
    /// an integer ID for this employee, guaranteed to be unique.
    /// </returns> 
    public int getId()
    {
        return id;
    }

    /// <returns> 
    /// a String name for this employee, NOT guaranteed to be unique.
    /// </returns> 
    public string getName()
    {
        return name;
    }

    /// <returns> 
    /// a List of employees which report to this employee.  This list may be empty, but will
    /// never be null.
    /// </returns> 
    public IList<Employee> getReports()
    {
        return reports;
    }

    /// <summary> 
    /// Adds the provided employee as a report of this employee. 
    /// </summary> 
    public void addReport(Employee employee)
    {
        reports.Add(employee);
    }
}
static void Main(字符串[]args)
{
Dictionary employeeMap=新字典();
员工ceo=null,第一名员工=null,第二名员工=null;
/*//样本输入
列表输入=新列表();
输入。添加(“员工1A”);
输入。添加(“员工2 B”);
输入。添加(“员工3 C”);
输入。添加(“员工4 D”);
输入。添加(“员工5 E”);
输入。添加(“员工6 F”);
输入。添加(“员工7 G”);
输入。添加(“员工8小时”);
输入。添加(“员工9 I”);
输入。添加(“员工10 J”);
输入。添加(“员工11K”);
输入。添加(“员工12 L”);
输入。添加(“员工13M”);
输入。添加(“报告1-2”);
输入。添加(“报告13”);
输入。添加(“报告2-4”);
输入。添加(“报告2.5”);
输入。添加(“报告2 6”);
输入。添加(“报告5-7”);
输入。添加(“报告5-8”);
输入。添加(“报告6-9”);
输入。添加(“报告6-10”);
输入。添加(“报告3-11”);
输入。添加(“报告3 12”);
输入。添加(“报告3 13”);
输入。添加(“参数1 9 13”)*/
弦线;
而((line=Console.ReadLine())!=null)
{
string[]tokens=line.Split();
字符串类型=令牌[0];
if(类型等于(“员工”))
{
int id=int.Parse(标记[1]);
字符串名称=令牌[2];
添加(id,新员工(id,姓名));
}
else if(type.Equals(“报告”))
{
Employee manager=employeeMap[int.Parse(令牌[1]);
Employee report=employeeMap[int.Parse(令牌[2]);
经理。添加报告(报告);
}
else if(type.Equals(“params”))
{
ceo=employeeMap[int.Parse(令牌[1]);
firstEmployee=employeeMap[int.Parse(令牌[2]);
secondEmployee=employeeMap[int.Parse(令牌[3]);
}
其他的
{
//忽略注释和空白
}
}
 static void Main(string[] args)
    {
        Dictionary<int, Employee> employeeMap = new Dictionary<int, Employee>();
        Employee ceo = null, firstEmployee = null, secondEmployee = null;
        /*//Sample input
         List<string> input = new List<string>();
         input.Add("employee 1 A");
         input.Add("employee 2 B");
         input.Add("employee 3 C");
         input.Add("employee 4 D");
         input.Add("employee 5 E");
         input.Add("employee 6 F");
         input.Add("employee 7 G");
         input.Add("employee 8 H");
         input.Add("employee 9 I");
         input.Add("employee 10 J");
         input.Add("employee 11 K");
         input.Add("employee 12 L");
         input.Add("employee 13 M");

         input.Add("report 1 2");
         input.Add("report 1 3");

         input.Add("report 2 4");
         input.Add("report 2 5");
         input.Add("report 2 6");

         input.Add("report 5 7");
         input.Add("report 5 8");

         input.Add("report 6 9");
         input.Add("report 6 10");

         input.Add("report 3 11");
         input.Add("report 3 12");
         input.Add("report 3 13");

         input.Add("params 1 9 13");*/

        string line;
        while ((line = Console.ReadLine()) != null)
        {
            string[] tokens = line.Split();
            string type = tokens[0];

            if (type.Equals("employee"))
            {
                int id = int.Parse(tokens[1]);
                String name = tokens[2];
                employeeMap.Add(id, new Employee(id, name));
            }
            else if (type.Equals("report"))
            {
                Employee manager = employeeMap[int.Parse(tokens[1])];
                Employee report = employeeMap[int.Parse(tokens[2])];
                manager.addReport(report);
            }
            else if (type.Equals("params"))
            {
                ceo = employeeMap[int.Parse(tokens[1])];
                firstEmployee = employeeMap[int.Parse(tokens[2])];
                secondEmployee = employeeMap[int.Parse(tokens[3])];
            }
            else
            {
                // ignore comments and whitespace
            }
        }

        Employee result = closestCommonManager(ceo, firstEmployee, secondEmployee);
    } 
public static Employee closestCommonManager(Employee ceo, Employee firstEmployee, Employee secondEmployee)
    {
        Stack<Employee> firstManagers = new Stack<Employee>();
        Stack<Employee> secondManagers = new Stack<Employee>();
        if (ceo.getReports().Count > 0)
        {
            searchManager(ceo, firstEmployee, firstManagers);
            searchManager(ceo, secondEmployee, secondManagers);
            if (firstManagers.Contains(secondEmployee))
            {
                return secondEmployee; //closest manager as this is managing the first one
            }
            if (secondManagers.Contains(firstEmployee))
            {
                return firstEmployee; //closest manager as this is managing the second one
            }

            //check for closest match

            //make them equal in length.
            while (firstManagers.Count > secondManagers.Count)
            {
                firstManagers.Pop();
            }

            while (secondManagers.Count > firstManagers.Count)
            {
                secondManagers.Pop();
            }
            int checkCount = firstManagers.Count;
            for (int i = 0; i < checkCount; i++)
            {
                if (firstManagers.Peek().getId() == secondManagers.Peek().getId())
                {
                    return firstManagers.Pop();
                }
                else
                {
                    firstManagers.Pop();
                    secondManagers.Pop();
                }
            }
        }
        return null;
    }

    private static bool searchManager(Employee manager, Employee emp, Stack<Employee> graph)
    {
        bool res = false;
        graph.Push(manager);
        foreach (Employee e in manager.getReports())
        {
            if (e.getId() == emp.getId())
            {
                res = true;
                break;
            }
            else
            {
                if (e.getReports().Count > 0)
                {
                    if (searchManager(e, emp, graph))
                    {
                        return true;
                    }
                    else
                    {
                        graph.Pop();
                    }
                }
            }
        }
        return res;
    }

 public sealed class Employee
{

    private readonly int id;
    private readonly string name;
    private readonly List<Employee> reports;

    public Employee(int id, string name)
    {
        this.id = id;
        this.name = name;
        this.reports = new List<Employee>();
    }

    /// <returns> 
    /// an integer ID for this employee, guaranteed to be unique.
    /// </returns> 
    public int getId()
    {
        return id;
    }

    /// <returns> 
    /// a String name for this employee, NOT guaranteed to be unique.
    /// </returns> 
    public string getName()
    {
        return name;
    }

    /// <returns> 
    /// a List of employees which report to this employee.  This list may be empty, but will
    /// never be null.
    /// </returns> 
    public IList<Employee> getReports()
    {
        return reports;
    }

    /// <summary> 
    /// Adds the provided employee as a report of this employee. 
    /// </summary> 
    public void addReport(Employee employee)
    {
        reports.Add(employee);
    }
}