Java – a variant of “looking for a common ancestor”

I recently had a telephone interview It encodes the problem as part of the whole process

A   
   /  
  B 
  | \ 
  C  E  
  |  |  
  D  F  
  \  /  
   G

In this case, given the tree and nodes F and D, the closest common ancestor will be B. the second twist is that the tree is presented as an array The implementation method has the following inputs: public string getca (string [] nodes, string []] parentnodes, string targetnode1, string targetnode2). In this example, nodes = {"g", "F", "e", "d", "C", "B", "a"} and parentnodes = {"F", "d"}, {"e"}, {"B"}, {"C"}, {"a"}, null} basically for nodes [i], the parent node is parentnodes [i]. To tell you the truth, I am completely panicked (already very nervous) And it took a long time to find the answer Although I think this is a recursive solution, I have come up with an iterative solution. As far as I know, it is feasible: I push nodes in the queue, and then rise the first target node and then the second node Once I find a node i have encountered, I think it is the solution (annotated to clear things)

public String getCA(String[] nodes,String[][] parentNodes,String targetNode2) {  
        if(nodes == null || parentNodes == null){  
            throw new IllegalArgumentException();  
        }  

        Map<String,String[]> map = new HashMap<String,String[]>();  
        for(int i = 0; i < nodes.length; i++){  
            map.put(nodes[i],parentNodes[i]);  
        }  
        //These are the parents visited as we go up  
        Set<String> parentsSeen = new HashSet<String>();  
        parentsSeen.add(targetNode1);  

        Queue<String> path = new LinkedList<String>();  
        String[] parents = map.get(targetNode1);  
        //The root is the common parent  
        if(parents == null){  
            return targetNode1;  
        }   

        //Build the path up  
        for(String parent:parents){  
            path.add(parent);  
        }  
        while(!path.isEmpty()){  
            String currentParent = path.remove();  
            parentsSeen.add(currentParent);  
            parents = map.get(currentParent);  
            if(parents == null){  
                continue;   
            }  
            for(String parent:parents){  
                path.add(parent);  
            }  
        }  

        parents = map.get(targetNode2);  
        //It is the root,so it is the common parent  
        if(parents == null){  
            return targetNode2;  
        }  
        //Start going up for the targetNode2. The first parent that we have already visited is the common parent  
        for(String parent:parents){  
            if(parentsSeen.contains(parent)){  
                return parent;  
            }  
            path.add(parent);  
        }  

        while(!path.isEmpty()){  
            String currentParent = path.remove();  
            if(parentsSeen.contains(currentParent)){  
                return currentParent;  
            }             
            parents = map.get(currentParent);  
            if(parents == null){  
                continue;  
            }  
            for(String parent:parents){  
                path.add(parent);  
            }  
        }  
        return null;            
    }

I didn't get a forward call Now that I'm "self-taught", I'm interested in understanding how I screwed up here As this is a technical problem, I don't think it is a subjective problem. I hope I can get help from experienced people So, as a colleague programmer, how would you handle this problem? How would you evaluate my solution? What do I need to do to improve my skills? You can be as straightforward as possible As long as I can understand what the problem is and learn it, I will be satisfied

Solution

I don't even know what "closest" means Consider the following chart:

I
   /\
  /  \
 /    \
H      E
|\    /|
| \  / |
G  \/  D
|  /\  |
| /  F C
|/    \|
A      B

There are two common ancestors a and B, h and E. h is the distance between a and B E is distance 1 from a, but distance b is 3 Which do I choose?

In addition, no matter what your answer to this question is, it doesn't work to find a group of ancestors from one person and then make a BFS from another person Find all ancestors of a, then BFS from B, find H first, find all ancestors of B, and then BFS from a, find e first. As an opponent, I can switch between a and B to make your algorithm fail, no matter what choice you make (2 / 2 or 1 / 3 is better)

Therefore, the correct algorithm must be more complex than ancestor set calculation plus BFS Unless you tell me how to make this choice, I'm not sure if I can determine the correct algorithm

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>