Get last node of the binary tree following given pattern starting from X
Given a binary tree, target node X and a string patt. The task is to find the last node of the binary tree following the pattern starting from X. Pattern may contain only five types of character ‘p’, ‘l’, ‘r’, ‘m’ and ‘n’. For any character encountered:
- p: Get to the parent of the current node.
- l: Get to the left child of the current node.
- r: Get to the right child of the current node.
- m: Get to the left sibling in the same level.
- n: Get to the right sibling in the same level.
Note that if the node doesn’t exist corresponding to any character then skip that character and remain on the current node.
Examples:
Input: 10 / \ 12 13 / \ 14 15 / \ / \ 21 22 23 24 X = 14, patt = "npmrprrlm" Output: 22 Starting from the target node 14 n: 14 -> 15 p: 15 -> 13 m: 13 -> 12 r: 12 -> 12 (there is no right child) p: 12 -> 10 r: 10 -> 13 r: 13 -> 15 l: 15 -> 23 m: 23 -> 22 Input: 5 / \ 16 8 X = 16, patt = "pppp" Output: 5
Approach:
- Create an auxiliary tree from the original tree but include three extra pointers (parent pointer, left and right sibling pointers).
- Parent pointer will point to the parent of the current node.
- Left pointer will point to the left sibling.
- Right pointer will point to the right sibling.
- Check the image below:
- After creation of this tree, we can easily traverse the given pattern.
- If any node doesn’t exist corresponding any character then simply skip that character.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; // A Tree node struct Node { int key; struct Node *left, *right; }; // Utility function to create a new node Node* newNode( int key) { Node* temp = new Node; temp->key = key; temp->left = temp->right = NULL; return (temp); } struct auxNode { int key; auxNode *left, *right, *parent; // Pointer will point the left node // at the same level in the tree auxNode* llNode; // Pointer will point the right node // at the same level in the tree auxNode* rlNode; }; auxNode* newAuxNode( int key) { auxNode* temp = new auxNode; temp->key = key; temp->left = temp->right = temp->parent = temp->llNode = temp->rlNode = NULL; return temp; } // Function to create the auxiliary tree auxNode* createAuxTree(Node* root) { if (root == NULL) return NULL; auxNode* auxTree = newAuxNode(root->key); auxTree->left = createAuxTree(root->left); auxTree->right = createAuxTree(root->right); return auxTree; } // Function for arranging the parent node for every node void makeParentNodePoint(auxNode* auxTree, auxNode* prev_ptr) { if (auxTree == NULL) return ; // Set the parent if (prev_ptr != NULL) { auxTree->parent = prev_ptr; } // Recur for left and right sub-trees makeParentNodePoint(auxTree->left, auxTree); makeParentNodePoint(auxTree->right, auxTree); } // Function for arranging the left and right // node for every node at the same level void makeSameLevelNodePoint(auxNode* auxTree) { queue<auxNode*> qu; qu.push(auxTree); while (!qu.empty()) { int qsize = qu.size(); while (qsize--) { auxNode* top_ele; top_ele = qu.front(); qu.pop(); if (qsize) { top_ele->rlNode = qu.front(); qu.front()->llNode = top_ele; } if (top_ele->left != NULL) { qu.push(top_ele->left); } if (top_ele->right != NULL) { qu.push(top_ele->right); } } } } // Function to return the target node address auxNode* getTargetNodeAddress(auxNode* auxTree, int tNode) { if (auxTree == NULL) return NULL; if (auxTree->key == tNode) { return auxTree; } auxNode* is_null = getTargetNodeAddress(auxTree->left, tNode); if (is_null != NULL) return is_null; return getTargetNodeAddress(auxTree->right, tNode); } // Utility function to print the last node void printNode(auxNode* auxTree, auxNode* target_node, string pattern) { // Perform the movement for ( int i = 0; i < pattern.length(); i++) { switch (pattern[i]) { // Get to the parent case 'p' : case 'P' : if (target_node->parent != NULL) { target_node = target_node->parent; } break ; // Get to the left child case 'l' : case 'L' : if (target_node->left != NULL) { target_node = target_node->left; } break ; // Get to the right child case 'r' : case 'R' : if (target_node->right != NULL) target_node = target_node->right; break ; // Get to the left sibling in the same level case 'm' : case 'M' : if (target_node->llNode != NULL) target_node = target_node->llNode; break ; // Get to the right sibling in the same level case 'n' : case 'N' : if (target_node->rlNode != NULL) target_node = target_node->rlNode; break ; default : return ; } } cout << target_node->key; } // Function to print the last node // according to the pattern void printNodeUsingPattern(Node* root, string pattern, int tNode) { // Function will create auxiliary tree same as // original tree with left child and right child auxNode* auxTree = createAuxTree(root); // Function will make every node // point to its parent node makeParentNodePoint(auxTree, NULL); // Function will make every node point to its // left and right node at the same level makeSameLevelNodePoint(auxTree); // Function will give the address of the target node auxNode* target_node = getTargetNodeAddress(auxTree, tNode); // If target node found if (target_node != NULL) { // Function call to print the last node // according to the given pattern printNode(auxTree, target_node, pattern); } else cout << "-1" ; } // Driver code int main() { Node* root = newNode(10); root->left = newNode(12); root->right = newNode(13); root->right->left = newNode(14); root->right->right = newNode(15); root->right->left->left = newNode(21); root->right->left->right = newNode(22); root->right->right->left = newNode(23); root->right->right->right = newNode(24); int target_node = 14; string str = "npmrprrlm" ; printNodeUsingPattern(root, str, target_node); return 0; } |
Python3
# Python3 implementation of the approach import queue # A Tree node class Node: def __init__( self ,key): self .left = None self .right = None self .key = key class auxNode: def __init__( self ,key): self .left = None self .right = None self .key = key self .parent = None # Pointer will point the left node # at the same level in the tree self .llNode = None # Pointer will point the right node # at the same level in the tree self .rlNode = None def newAuxNode(key): temp = auxNode(key) return temp def createAuxTree(root): if (root = = None ) : return None auxTree = auxNode(root.key) auxTree.left = createAuxTree(root.left) auxTree.right = createAuxTree(root.right) return auxTree # Function for arranging the # parent node for every node def makeParentNodePoint(auxTree, prev_ptr): if (auxTree = = None ): return ; # Set the parent if (prev_ptr ! = None ) : auxTree.parent = prev_ptr #print("Parent : ",auxTree.parent.key) # Recur for left and right sub-trees makeParentNodePoint(auxTree.left, auxTree) makeParentNodePoint(auxTree.right, auxTree) # Function for arranging the left and right # node for every node at the same level def makeSameLevelNodePoint(auxTree): qu = queue.Queue(maxsize = 50 ) qu.put(auxTree) while ( not qu.empty()) : size = qu.qsize() while (size) : size - = 1 top_ele = qu.get(); if (size) : front = qu.get() top_ele.rlNode = front front.llNode = top_ele # since we don't have peek function # in python creating 2nd queue # to store elements below peek element qu2 = queue.Queue(maxsize = 50 ) while not qu.empty(): a = qu.get() qu2.put(a) # putting back front element # in queue 1 all elements which # were behind it in original queue qu.put(front) while not qu2.empty(): qu.put(qu2.get()) if (top_ele.left ! = None ) : qu.put(top_ele.left) if (top_ele.right ! = None ) : qu.put(top_ele.right) # Function to return the target node address def getTargetNodeAddress(auxTree, tNode): if (auxTree = = None ): return None if (auxTree.key = = tNode) : return auxTree is_null = getTargetNodeAddress(auxTree.left, tNode) if (is_null ! = None ): return is_null return getTargetNodeAddress(auxTree.right, tNode) # Utility function to print the last node def printNode(auxTree, target_node, pattern): # Perform the movement for i in range ( len (pattern)) : # Get to the parent if pattern[i] = = 'p' or pattern[i] = = 'P' : if (target_node.parent ! = None ): target_node = target_node.parent # Get to the left child elif pattern[i] = = 'l' or pattern[i] = = 'L' : if (target_node.left ! = None ) : target_node = target_node.left # Get to the right child elif pattern[i] = = 'r' or pattern[i] = = 'R' : if (target_node.right ! = None ): target_node = target_node.right # Get to the left sibling in the same level elif pattern[i] = = 'm' or pattern[i] = = 'M' : if (target_node.llNode ! = None ): target_node = target_node.llNode # Get to the right sibling in the same level elif pattern[i] = = 'n' or pattern[i] = = 'N' : if (target_node.rlNode ! = None ): target_node = target_node.rlNode else : return print (target_node.key, end = ' ' ) # Function to print the last node # according to the pattern def printNodeUsingPattern(root, pattern, tNode): # Function will create auxiliary tree same as # original tree with left child and right child auxTree = createAuxTree(root) # Function will make every node # point to its parent node makeParentNodePoint(auxTree, None ) # Function will make every node point to its # left and right node at the same level makeSameLevelNodePoint(auxTree) # Function will give the address of the target node target_node = getTargetNodeAddress(auxTree, tNode) # If target node found if (target_node ! = None ) : # Function call to print the last node # according to the given pattern printNode(auxTree, target_node, pattern); else : print ( "-1" ) # Driver Code root = Node( 10 ) root.left = Node( 12 ) root.right = Node( 13 ) root.right.left = Node( 14 ) root.right.right = Node( 15 ) root.right.left.left = Node( 21 ) root.right.left.right = Node( 22 ) root.right.right.left = Node( 23 ) root.right.right.right = Node( 24 ) target_node = 14 string = "npmrprrlm" printNodeUsingPattern(root, string, target_node) # This code is contributed by Sadik Ali |
Output:
22
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.