Given a binary tree, target node X and a string pattern. 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 above image:
- 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++ 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;
} |
// Java Program for above approach import java.util.*;
// A Tree node class Node {
int key;
Node left, right;
// Utility function to create a new node
Node( int item)
{
key = item;
left = right = null ;
}
} class AuxNode {
int key;
AuxNode left, right, parent, llNode, rlNode;
AuxNode( int item)
{
key = item;
left = right = parent = llNode = rlNode = null ;
}
} class GFG {
static AuxNode newAuxNode( int key)
{
return new AuxNode(key);
}
// Function to create the auxiliary tree
static 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
static 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
static void makeSameLevelNodePoint(AuxNode auxTree)
{
Queue<AuxNode> q = new LinkedList<AuxNode>();
q.add(auxTree);
while (!q.isEmpty()) {
int qsize = q.size();
while (qsize-- > 0 ) {
AuxNode topEle = q.peek();
q.remove();
if (qsize > 0 ) {
topEle.rlNode = q.peek();
q.peek().llNode = topEle;
}
if (topEle.left != null ) {
q.add(topEle.left);
}
if (topEle.right != null ) {
q.add(topEle.right);
}
}
}
}
// Function to return the target node address
static 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
static void printNode(AuxNode auxTree,
AuxNode target_node,
String pattern)
{
// Perform the movement
for ( int i = 0 ; i < pattern.length(); i++) {
switch (pattern.charAt(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 ;
}
}
System.out.print(target_node.key);
}
// Function to print the last node
// according to the pattern
static 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 {
System.out.print( "-1" );
}
}
// Driver code
public static void main(String args[])
{
Node root = new Node( 10 );
root.left = new Node( 12 );
root.right = new Node( 13 );
root.right.left = new Node( 14 );
root.right.right = new Node( 15 );
root.right.left.left = new Node( 21 );
root.right.left.right = new Node( 22 );
root.right.right.left = new Node( 23 );
root.right.right.right = new Node( 24 );
int target_node = 14 ;
String str = "npmrprrlm" ;
printNodeUsingPattern(root, str, target_node);
}
} // This code is contributed by Prince Kumar |
# 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 |
<script> // JavaScript implementation of the approach
// Node structure of the tree
class Node
{
constructor(key) {
this .left = null ;
this .right = null ;
this .key = key;
}
}
// Utility function to create a new node
function newNode(key)
{
let temp = new Node(key);
return (temp);
}
class auxNode
{
constructor(key) {
this .left = null ;
this .right = null ;
this .parent = null ;
this .llNode = null ;
this .rlNode = null ;
this .key = key;
}
}
function newAuxNode(key)
{
let temp = new auxNode(key);
return temp;
}
// Function to create the auxiliary tree
function createAuxTree(root)
{
if (root == null )
return null ;
let 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
function makeParentNodePoint(auxTree, 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
function makeSameLevelNodePoint(auxTree)
{
let qu = [];
qu.push(auxTree);
while (qu.length > 0)
{
let qsize = qu.length;
while (qsize-- > 0)
{
let top_ele;
top_ele = qu[0];
qu.shift();
if (qsize > 0)
{
top_ele.rlNode = qu[0];
qu[0].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
function getTargetNodeAddress(auxTree, tNode)
{
if (auxTree == null )
return null ;
if (auxTree.key == tNode)
{
return auxTree;
}
let 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
function printNode(auxTree, target_node, pattern)
{
// Perform the movement
for (let 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 ;
}
}
document.write(target_node.key);
}
// Function to print the last node
// according to the pattern
function printNodeUsingPattern(root, pattern, tNode)
{
// Function will create auxiliary tree same as
// original tree with left child and right child
let 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
let 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
document.write( "-1" );
}
let 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);
let target_node = 14;
let str = "npmrprrlm" ;
printNodeUsingPattern(root, str, target_node);
</script> |
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
// A Tree node public class Node {
public int key;
public Node left, right;
// Utility function to create a new node
public Node( int item)
{
key = item;
left = right = null ;
}
} public class AuxNode {
public int key;
public AuxNode left, right, parent, llNode, rlNode;
public AuxNode( int item)
{
key = item;
left = right = parent = llNode = rlNode = null ;
}
} public class GFG {
public static AuxNode newAuxNode( int key)
{
return new AuxNode(key);
}
// Function to create the auxiliary tree
public static 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
public static 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
public static void
makeSameLevelNodePoint(AuxNode auxTree)
{
Queue<AuxNode> q = new Queue<AuxNode>();
q.Enqueue(auxTree);
while (q.Count > 0) {
int qsize = q.Count;
while (qsize-- > 0) {
AuxNode topEle = q.Peek();
q.Dequeue();
if (qsize > 0) {
topEle.rlNode = q.Peek();
q.Peek().llNode = topEle;
}
if (topEle.left != null ) {
q.Enqueue(topEle.left);
}
if (topEle.right != null ) {
q.Enqueue(topEle.right);
}
}
}
}
// Function to return the target node address
public static 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
public static 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 ;
}
}
Console.Write(target_node.key);
}
// Function to print the last node
// according to the pattern
static 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 {
Console.Write( "-1" );
}
}
// Driver code
static void Main()
{
Node root = new Node(10);
root.left = new Node(12);
root.right = new Node(13);
root.right.left = new Node(14);
root.right.right = new Node(15);
root.right.left.left = new Node(21);
root.right.left.right = new Node(22);
root.right.right.left = new Node(23);
root.right.right.right = new Node(24);
int target_node = 14;
string str = "npmrprrlm" ;
printNodeUsingPattern(root, str, target_node);
}
} // The code is contributed by Nidhi goel. |
22
Time Complexity: The time complexity of the code is O(n), where n is the number of nodes in the tree.
Auxiliary Space: The Auxiliary Space of the code is also O(n), as the auxiliary tree takes up linear space in the number of nodes in the original tree.