Data structure problem collection-minimal common ancestor problem

Source: Internet
Author: User

As an engineering party, in the race of the big God in the face of the road will always feel their strength to catch the urgency. The great God can always according to the different problems, easily to the solution of the problem, however, I can only use the so-called "intuitive method" consolation, said more are tears ah. However, face their own theoretical shortcomings, catching up or necessary, after all, to really step into the industry, theoretical knowledge is not less AH. (such as the hash Map of various languages, their core can be red and black trees AH)

Since the TA asks the blog to be intuitive and easy to understand, let's start by recursion. method One: Recursive method

According to the requirements of the topic, if a two node has the same common ancestor, then there are two cases: either one is a public ancestor, and the other is in its Shari, or two nodes are in the left and right subtree of the public node. (What, two nodes in the same subtree of a public node?) In that case, the direct sub-node on one side is not a common node? In this way, we can design our own programs as follows:

classSolution { Public: TreeNode* Lowestcommonancestor (treenode* root, treenode* p, treenode*q) {//Tail end of the tree, nothing found        if(!root)returnNULL; //p or Q found, return non-null value as signal        if((root==p) | | (root==q))returnRoot; //Find p or Q on left and right branchtreenode* R_left = This->lowestcommonancestor (root->Left , p, q); TreeNode* R_right = This->lowestcommonancestor (root->Right , p, q); //p and Q found respectively on branches, return root as result        if(R_left &&r_right)returnRoot; //Only one branch contains target node, return non-null value as signal        Else if(R_left)returnR_left; Else            returnR_right; }};

The program is executed recursively. First, for the incoming node, if it is an empty node, it indicates that the end of the tree has been reached, but no p or q is found, and the return null indicates that no found. If Root is P or q, then we find P or Q, and the return p or Q indicates that p or q is found on the current recursive path. For the path passing through the recursive process, if the left and right branches have return nodes, then according to the above analysis, happy, root is the result we are looking for. If only one branch in the left and right returns a non-null signal, then the found node is returned, indicating that the node is still found on my branch. The program also implies that both branches do not find the node, while returning null, then return to the previous layer of the inevitable is null (that is, not found).

Obviously, in the worst case, the method may require access to all nodes, and if n represents the number of nodes, the maximum complexity can be up to O (n).

Method Two: Ergodic method

Again, it's a good idea to traverse the tree. In the process of traversing the tree node, we can maintain a stack containing a cascade of nodes, representing the path from the current node to the root, respectively, when the P and Q are found to compare two stacks, then the smallest common ancestor is easy to find. (In theory, there is no need to deliberately maintain a stack, because the function call (recursive) itself has a call stack, but this insignificant problem of stealing lazy I think it is not serious)

1 classSolution {2  Public:3     BOOLTraverse (treenode* root, treenode* target, vector<treenode*>&stack)4 {stack.push_back (root);5         6         if(root==target)7             return true;8         Else9{BOOLresult;Ten              One             if((Root->left) && (Traverse (root->left,target,stack ))) A                 return true; -             Else if((root->right) && (Traverse (root->right,target,stack ))) -                 return true; the Stack.pop_back (); -             return false; -         } -     } +  -Treenode* lowestcommonancestor (treenode* root, treenode* p, treenode*q) +{vector<treenode*>stack_p, stack_q; AUnsignedintmin_stack_size; atUnsignedinti =0; -treenode* result =NULL; -          - Traverse (root,p,stack_p); - Traverse (root,q,stack_q); -          inMin_stack_size =min (stack_p.size (), stack_q.size ()); -          while((i<min_stack_size) && (stack_p[i]==Stack_q[i])) to{result =Stack_p[i]; +i++; -         } the          *         returnresult; $     }Panax Notoginseng};

The complexity of this method is also O (n), and the execution speed on the leetcode looks similar to the previous method.

Method Three: Establish a reverse index

Now let's think of a situation, if we want to query the same tree multiple times for the smallest common ancestor? Obviously in this case, it is not too economical to do either of the first two methods in each call. At this point we can expand the existing tree, set up a reverse index to its parent node for each node, so that it becomes more efficient to query the minimum common ancestor for any two nodes.

Limited to the data structure of the node that leetcode the tree, and the C + + runtime is not able to expand the members of the data type (so dynamic language Dafa is good), there is no code. The simple idea is to traverse the entire tree first, removing the root node and establishing pointers to the parent node for all other nodes. And then from two given nodes up query, constitute two precursor sequence (said very Xuan actually with the last ask to get two stacks is exactly the same), and then find the smallest common ancestor.

The complexity of establishing such a reverse index is O (n), so it is not an economic practice to run it only once, but multiple times, the complexity of the method tends to be lower than the first two. If the number of layers of the tree is m, then every query complexity is O (M), as long as the tree is not as hard to look like a linked list (in other words, compare "balance", m not more than a few times log (n)), the advantage of method three can be reflected.

Jiang (yi) (yin)

Coding Jump really wood there is the need, why do not use GitHub classroom to decorate homework? What, you said there was no way to automate the assignment? Travis CI This automatic build tool can do ah, make a web Hook, whenever someone submits a job to trigger the Travis CI compile run sample, and then output the test results of the log.

Data structure problem collection-minimal common ancestor problem

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.