Lowest Common Ancestor of a Binary Tree

后端 未结 6 573
栀梦
栀梦 2021-02-02 00:01

This is a popular interview question and the only article I can find on the topic is one from TopCoder. Unfortunately for me, it looks overly complicated from an interview answe

6条回答
  •  情书的邮戳
    2021-02-02 00:58

    The obvious solution, that uses log(n) space, (n is the number of nodes) is the algorithm you mentioned. Here's an implementation. In the worst case it takes O(n) time (imagine that one of the node you are searching common ancestor for includes the last node).

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
        class Node
        {
            private static int counter = 0;
            private Node left = null;
            private Node right = null;
            public int id = counter++;
    
            static Node constructTreeAux(int depth)
            {
                if (depth == 0)
                    return null;
                Node newNode = new Node();
                newNode.left = constructTree(depth - 1);
                newNode.right = constructTree(depth - 1);
                return newNode;
            }
    
            public static Node constructTree(int depth)
            {
                if (depth == 0)
                    return null;
                Node root = new Node();
                root.left = constructTreeAux(depth - 1);
                root.right = constructTreeAux(depth - 1);
                return root;
            }
    
            private List findPathAux(List pathSoFar, int searchId)
            {
                if (this.id == searchId)
                {
                    if (pathSoFar == null)
                        pathSoFar = new List();
                    pathSoFar.Add(this);
                    return pathSoFar;
                }
                if (left != null)
                {
                    List result = left.findPathAux(null, searchId);
                    if (result != null)
                    {
                        result.Add(this);
                        return result;
                    }
                }
                if (right != null)
                {
                    List result = right.findPathAux(null, searchId);
                    if (result != null)
                    {
                        result.Add(this);
                        return result;
                    }
                }
                return null;
            }
    
            public static void printPath(List path)
            {
                if (path == null)
                {
                    Console.Out.WriteLine(" empty path ");
                    return;
                }
                Console.Out.Write("[");
                for (int i = 0; i < path.Count; i++)
                    Console.Out.Write(path[i] + " ");
                Console.Out.WriteLine("]");
            }
    
            public override string ToString()
            {
                return id.ToString();
            }
    
            /// 
            /// Returns null if no common ancestor, the lowest common ancestor otherwise.
            /// 
            public Node findCommonAncestor(int id1, int id2)
            {
                List path1 = findPathAux(null, id1);
                if (path1 == null)
                    return null;
                path1 = path1.Reverse().ToList();
                List path2 = findPathAux(null, id2);
                if (path2 == null)
                    return null;
                path2 = path2.Reverse().ToList();
                Node commonAncestor = this;
                int n = path1.Count < path2.Count? path1.Count : path2.Count;
                printPath(path1);
                printPath(path2);
                for (int i = 0; i < n; i++)
                {
                    if (path1[i].id == path2[i].id)
                        commonAncestor = path1[i];
                    else
                        return commonAncestor;
                }          
                return commonAncestor;
            }
    
            private void printTreeAux(int depth)
            {
                for (int i = 0; i < depth; i++)
                    Console.Write("  ");
                Console.WriteLine(id);
                if (left != null)
                    left.printTreeAux(depth + 1);
                if (right != null)
                    right.printTreeAux(depth + 1);
            }
    
            public void printTree()
            {
                printTreeAux(0);
            }
            public static void testAux(out Node root, out Node commonAncestor, out int id1, out int id2)
            {
                Random gen = new Random();
                int startid = counter;
                root = constructTree(5);
                int endid = counter;
    
                int offset = gen.Next(endid - startid);
                id1 = startid + offset;
                offset = gen.Next(endid - startid);
                id2 = startid + offset;
                commonAncestor = root.findCommonAncestor(id1, id2);
    
            }
            public static void test1()
            {
                Node root = null, commonAncestor = null;
                int id1 = 0, id2 = 0;
               testAux(out root, out commonAncestor, out id1, out id2);
                root.printTree();
                 commonAncestor = root.findCommonAncestor(id1, id2);
                if (commonAncestor == null)
                    Console.WriteLine("Couldn't find common ancestor for " + id1 + " and " + id2);
                else
                    Console.WriteLine("Common ancestor for " + id1 + " and " + id2 + " is " + commonAncestor.id);
            }
        }
    }
    

提交回复
热议问题