You are given a set of links, e.g.
a ---> b
b ---> c
b ---> d
a ---> e
Print the tree that would form when each pair of these links that has the same character as start and end point is joined together. You have to maintain fidelity w.r.t. the height of nodes, i.e. nodes at height n from root should be printed at same row or column. For set of links given above, tree printed should be -
-->a
|-->b
| |-->c
| |-->d
|-->e
Note that these links need not form a single tree; they could form, ahem, a forest. Consider the following links
a ---> b
a ---> g
b ---> c
c ---> d
d ---> e
c ---> f
z ---> y
y ---> x
x ---> w
The output would be following forest.
-->a
|-->b
| |-->c
| | |-->d
| | | |-->e
| | |-->f
|-->g
-->z
|-->y
| |-->x
| | |-->w
You can assume that given links can form a tree or forest of trees only, and there are no duplicates among links.
Solution: The idea is to maintain two arrays, one array for tree nodes and other for trees themselves (we call this array forest). An element of the node array contains the TreeNode object that corresponds to respective character. An element of the forest array contains Tree object that corresponds to respective root of tree. It should be obvious that the crucial part is creating the forest here, once it is created, printing it out in required format is straightforward. To create the forest, following procedure is used -
Do following for each input link,
1. If start of link is not present in node array
Create TreeNode objects for start character
Add entries of start in both arrays.
2. If end of link is not present in node array
Create TreeNode objects for start character
Add entry of end in node array.
3. If end of link is present in node array.
If end of link is present in forest array, then remove it
from there.
4. Add an edge (in tree) between start and end nodes of link.
It should be clear that this procedure runs in linear time in number of nodes as well as of links - it makes only one pass over the links. It also requires linear space in terms of alphabet size. Following is Java implementation of above algorithm. In the following implementation characters are assumed to be only lower case characters from 'a' to 'z'.
Implementation:
Java
// Java program to create a custom tree from a given set of links.
// The main class that represents tree and has main method
public class Tree {
private TreeNode root;
/* Returns an array of trees from links input. Links are assumed to
be Strings of the form "<s> <e>" where <s> and <e> are starting
and ending points for the link. The returned array is of size 26
and has non-null values at indexes corresponding to roots of trees
in output */
public Tree[] buildFromLinks(String [] links) {
// Create two arrays for nodes and forest
TreeNode[] nodes = new TreeNode[26];
Tree[] forest = new Tree[26];
// Process each link
for (String link : links) {
// Find the two ends of current link
String[] ends = link.split(" ");
int start = (int) (ends[0].charAt(0) - 'a'); // Start node
int end = (int) (ends[1].charAt(0) - 'a'); // End node
// If start of link not seen before, add it two both arrays
if (nodes[start] == null)
{
nodes[start] = new TreeNode((char) (start + 'a'));
// Note that it may be removed later when this character is
// last character of a link. For example, let we first see
// a--->b, then c--->a. We first add 'a' to array of trees
// and when we see link c--->a, we remove it from trees array.
forest[start] = new Tree(nodes[start]);
}
// If end of link is not seen before, add it to the nodes array
if (nodes[end] == null)
nodes[end] = new TreeNode((char) (end + 'a'));
// If end of link is seen before, remove it from forest if
// it exists there.
else forest[end] = null;
// Establish Parent-Child Relationship between Start and End
nodes[start].addChild(nodes[end], end);
}
return forest;
}
// Constructor
public Tree(TreeNode root) { this.root = root; }
public static void printForest(String[] links)
{
Tree t = new Tree(new TreeNode('\0'));
for (Tree t1 : t.buildFromLinks(links)) {
if (t1 != null)
{
t1.root.printTreeIdented("");
System.out.println("");
}
}
}
// Driver method to test
public static void main(String[] args) {
String [] links1 = {"a b", "b c", "b d", "a e"};
System.out.println("------------ Forest 1 ----------------");
printForest(links1);
String [] links2 = {"a b", "a g", "b c", "c d", "d e", "c f",
"z y", "y x", "x w"};
System.out.println("------------ Forest 2 ----------------");
printForest(links2);
}
}
// Class to represent a tree node
class TreeNode {
TreeNode []children;
char c;
// Adds a child 'n' to this node
public void addChild(TreeNode n, int index) { this.children[index] = n;}
// Constructor
public TreeNode(char c) { this.c = c; this.children = new TreeNode[26];}
// Recursive method to print indented tree rooted with this node.
public void printTreeIdented(String indent) {
System.out.println(indent + "-->" + c);
for (TreeNode child : children) {
if (child != null)
child.printTreeIdented(indent + " |");
}
}
}
C#
// C# program to create a custom tree
// from a given set of links.
using System;
// The main class that represents tree
// and has main method
class Tree
{
public TreeNode root;
/* Returns an array of trees from links input.
Links are assumed to be Strings of the form
"<s> <e>" where <s> and <e> are starting and
ending points for the link. The returned array is
of size 26 and has non-null values at indexes
corresponding to roots of trees in output */
public Tree[] buildFromLinks(String [] links)
{
// Create two arrays for nodes and forest
TreeNode[] nodes = new TreeNode[26];
Tree[] forest = new Tree[26];
// Process each link
foreach (String link in links)
{
char []sep = {' ',' '};
// Find the two ends of current link
String[] ends = link.Split(sep);
int start = (int) (ends[0][0] - 'a'); // Start node
int end = (int) (ends[1][0] - 'a'); // End node
// If start of link not seen before,
// add it two both arrays
if (nodes[start] == null)
{
nodes[start] = new TreeNode((char) (start + 'a'));
// Note that it may be removed later when
// this character is last character of a link.
// For example, let we first see a--->b,
// then c--->a. We first add 'a' to array
// of trees and when we see link c--->a,
// we remove it from trees array.
forest[start] = new Tree(nodes[start]);
}
// If end of link is not seen before,
// add it to the nodes array
if (nodes[end] == null)
nodes[end] = new TreeNode((char) (end + 'a'));
// If end of link is seen before,
// remove it from forest if it exists there.
else forest[end] = null;
// Establish Parent-Child Relationship
// between Start and End
nodes[start].addChild(nodes[end], end);
}
return forest;
}
// Constructor
public Tree(TreeNode root) { this.root = root; }
public static void printForest(String[] links)
{
Tree t = new Tree(new TreeNode('\0'));
foreach (Tree t1 in t.buildFromLinks(links))
{
if (t1 != null)
{
t1.root.printTreeIdented("");
Console.WriteLine("");
}
}
}
// Driver Code
public static void Main(String[] args) {
String [] links1 = {"a b", "b c", "b d", "a e"};
Console.WriteLine("------------ Forest 1 ----------------");
printForest(links1);
String [] links2 = {"a b", "a g", "b c", "c d", "d e",
"c f", "z y", "y x", "x w"};
Console.WriteLine("------------ Forest 2 ----------------");
printForest(links2);
}
}
// Class to represent a tree node
public class TreeNode
{
TreeNode []children;
char c;
// Adds a child 'n' to this node
public void addChild(TreeNode n, int index)
{
this.children[index] = n;
}
// Constructor
public TreeNode(char c)
{
this.c = c; this.children = new TreeNode[26];
}
// Recursive method to print indented tree
// rooted with this node.
public void printTreeIdented(String indent)
{
Console.WriteLine(indent + "-->" + c);
foreach (TreeNode child in children)
{
if (child != null)
child.printTreeIdented(indent + " |");
}
}
}
// This code is contributed by Rajput-Ji
Python3
#Python code for the above approach
# The main class that represents tree
# and has main method
class TreeNode:
def __init__(self, c):
self.c = c
self.children = [None]*26
def addChild(self, n, index):
self.children[index] = n
def printTreeIdented(self, indent):
print(indent + "-->" + self.c)
for child in self.children:
if child:
child.printTreeIdented(indent + " |")
class Tree:
def __init__(self, root):
self.root = root
def buildFromLinks(self, links):
"""
Returns an array of trees from links input. Links are assumed to
be strings of the form "<s> <e>" where <s> and <e> are starting
and ending points for the link. The returned array is of size 26
and has non-null values at indexes corresponding to roots of trees
in output
"""
nodes = [None]*26
forest = [None]*26
for link in links:
start = ord(link[0]) - ord('a')
end = ord(link[2]) - ord('a')
# If start of link not seen before, add it two both arrays
if not nodes[start]:
nodes[start] = TreeNode(chr(start + ord('a')))
forest[start] = Tree(nodes[start])
# If end of link is not seen before, add it to the nodes array
if not nodes[end]:
nodes[end] = TreeNode(chr(end + ord('a')))
# If end of link is seen before, remove it from forest if
# it exists there.
else:
forest[end] = None
# Establish Parent-Child Relationship between Start and End
nodes[start].addChild(nodes[end], end)
return forest
@staticmethod
def printForest(links):
t = Tree(TreeNode('\0'))
for t1 in t.buildFromLinks(links):
if t1:
t1.root.printTreeIdented("")
print()
if __name__ == "__main__":
links1 = ["a b", "b c", "b d", "a e"]
print("------------ Forest 1 ----------------")
Tree.printForest(links1)
links2 = ["a b", "a g", "b c", "c d", "d e", "c f", "z y", "y x", "x w"]
print("------------ Forest 2 ----------------")
Tree.printForest(links2)
JavaScript
// Class to represent a node in the tree
class TreeNode {
constructor(c) {
// The character stored at this node
this.c = c;
// An array of 26 nodes to represent children of this node
this.children = new Array(26).fill(null);
}
// Method to add a child node to this node
addChild(n, index) {
this.children[index] = n;
}
// Method to print the tree with indentation
printTreeIdented(indent) {
document.write(indent + "-->" + this.c);
for (const child of this.children) {
if (child) {
child.printTreeIdented(indent + " |");
}
}
}
}
// Class to represent a tree
class Tree {
constructor(root) {
// The root node of this tree
this.root = root;
}
// Method to build trees from the given links
buildFromLinks(links) {
// An array to store all nodes in the tree
let nodes = new Array(26).fill(null);
// An array to store trees in the forest
let forest = new Array(26).fill(null);
// Iterating over all links to build the trees
for (const link of links) {
// Calculating the starting and ending points of the link
let start = link.charCodeAt(0) - 'a'.charCodeAt(0);
let end = link.charCodeAt(2) - 'a'.charCodeAt(0);
// If start of the link is not seen before, add it to both arrays
if (!nodes[start]) {
nodes[start] = new TreeNode(String.fromCharCode(start + 'a'.charCodeAt(0)));
forest[start] = new Tree(nodes[start]);
}
// If end of the link is not seen before, add it to the nodes array
if (!nodes[end]) {
nodes[end] = new TreeNode(String.fromCharCode(end + 'a'.charCodeAt(0)));
}
// If end of the link is seen before, remove it from the forest array if it exists there
else {
forest[end] = null;
}
// Establish Parent-Child Relationship between Start and End
nodes[start].addChild(nodes[end], end);
}
return forest;
}
// Method to print the forest of trees
static printForest(links) {
let t = new Tree(new TreeNode('\0'));
// Building the forest of trees from the given links
let forest = t.buildFromLinks(links);
// Iterating over all trees in the forest and printing them
for (const t1 of forest) {
if (t1) {
t1.root.printTreeIdented("");
document.write("<br>");
}
}
}
}
let links1 = ["a b", "b c", "b d", "a e"];
document.write("------------ Forest 1 ----------------"+"<br>");
Tree.printForest(links1);
let links2 = ["a b", "a g", "b c", "c d", "d e", "c f", "z y", "y x", "x w"];
document.write("------------ Forest 2 ----------------"+"<br>");
Tree.printForest(links2);
C++
#include <iostream>
#include <vector>
using namespace std;
// Class to represent a tree node
class TreeNode {
public:
vector<TreeNode*> children; // vector of child nodes
char c; // node's value
// Constructor
TreeNode(char c) { this->c = c; }
// Adds a child 'n' to this node
void addChild(TreeNode* n)
{
this->children.push_back(n);
}
// Recursive method to print indented tree rooted with
// this node.
void printTreeIndented(string indent)
{
cout << indent << "-->" << c << endl;
for (auto child : children) {
if (child != nullptr) {
child->printTreeIndented(indent + " |");
}
}
}
};
// The main class that represents a forest and has main
// method
class Tree {
private:
TreeNode* root;
public:
// Constructor
Tree(TreeNode* root) { this->root = root; }
TreeNode* getRoot() { return root; }
/* Returns an array of trees from links input. Links are
assumed to be Strings of the form "<s> <e>" where <s>
and <e> are starting and ending points for the link.
The returned array is of size 26 and has non-null
values at indexes corresponding to roots of trees
in output */
vector<Tree*> buildFromLinks(vector<string> links)
{
TreeNode* nodes[26]
= { nullptr }; // array of tree nodes
vector<Tree*> forest(
26, nullptr); // vector of tree roots
// Process each link
for (auto link : links) {
// Find the two ends of current link
char start = link[0]; // Start node
char end = link[2]; // End node
// If start of link not seen before, add it to
// both arrays
if (nodes[start - 'a'] == nullptr) {
nodes[start - 'a'] = new TreeNode(start);
forest[start - 'a']
= new Tree(nodes[start - 'a']);
}
// If end of link is not seen before, add it to
// the nodes array
if (nodes[end - 'a'] == nullptr) {
nodes[end - 'a'] = new TreeNode(end);
}
// If end of link is seen before, remove it from
// forest if it exists there.
else {
forest[end - 'a'] = nullptr;
}
// Establish Parent-Child Relationship between
// Start and End
nodes[start - 'a']->addChild(nodes[end - 'a']);
}
return forest;
}
};
// Function to print a forest
void printForest(std::vector<std::string> links)
{
Tree t(new TreeNode('\0'));
for (Tree* t1 : t.buildFromLinks(links)) {
if (t1 != nullptr) {
t1->getRoot()->printTreeIndented("");
std::cout << std::endl;
}
}
}
int main()
{
vector<string> links1 = { "a b", "b c", "b d", "a e" };
cout << "------------ Forest 1 ----------------"
<< endl;
printForest(links1);
vector<string> links2
= { "a b", "a g", "b c", "c d", "d e",
"c f", "z y", "y x", "x w" };
cout << "------------ Forest 2 ----------------"
<< endl;
printForest(links2);
return 0;
}
// This code is contributed by divyansh2212
Output------------ Forest 1 ----------------
-->a
|-->b
| |-->c
| |-->d
|-->e
------------ Forest 2 ----------------
-->a
|-->b
| |-->c
| | |-->d
| | | |-->e
| | |-->f
|-->g
-->z
|-->y
| |-->x
| | |-->w
Time Complexity: O(n) where n is the number of links in the input array.
Auxiliary Space: O(n)
Exercise: In the above implementation, endpoints of input links are assumed to be from set of only 26 characters. Extend the implementation where endpoints are strings of any length.
Similar Reads
Logic Building Problems
Logic building is about creating clear, step-by-step methods to solve problems using simple rules and principles. Itâs the heart of coding, enabling programs to think, reason, and arrive at smart solutions just like we do.Here are some tips for improving your programming logic: Understand the proble
2 min read
Directi Interview | Set 8 (Off-Campus)
I applied for Directi off-campus on its career website and I got a call. There were total 5 rounds. Online coding round: 1.5 hours There were a total of 3 questions. All of them were coding questions covering ad-hoc, dp ,hashing ,graphs etc and you could do it only if you do regular online competiti
9 min read
PayPal Interview Experience | Set 5 (On-Campus)
Around 800 students from our university were eligible to attend the interview process conducted by PayPal First round (online round) Conducted at hackerrank which had 15 MCQ ( technical + aptitude ) questions and a coding question. Program asked was Maximum amongst minimum in sub arrays. I did 12/15
3 min read
HCL Placement Paper | Logical Reasoning Set - 4
This is an HCL model placement paper on Logical Reasoning for placement preparation. This placement paper will cover logical reasoning questions that are asked in HCL recruitment drives and also strictly follows the pattern of questions asked in HCL interviews. It is recommended to solve each one of
7 min read
Accolite Interview | Set 2 (On-Campus)
Accolite came to our campus for recruitment. First Round Written Test: 30 MCQs in which question related to DS Networking OS Unix commands DBMS. Questions were easy. They selected 7 students out of around 60 students for next rounds. Tech Round 1: First of all interviewer see my resume then asked ab
4 min read
Morgan Stanley Interview | Set 11 (On-Campus)
Multiple Choice Questions Questions ranging from give the output of following C program to some theoretical concepts of OS etc. Coding 1. Give maximum subarray product in a given input array which can contain integers (including negative and zero). 2. Given a set of n coins of some denominations (ma
4 min read
MakeMyTrip Interview Experience | Set 7 (On-Campus)
Recently makemytrip visited our Campus and I got selected in recruitment drive.The placement drive consisted of 4 rounds. Round1: MCQ and coding round It was an online test of 60 minutes consisting of 20 aptitude question and 3 coding question. Platform used for the test was of makemytrip and slight
5 min read
Cvent Interview Experience (On campus for Internship and Full Time)
Technical attitude test(Round 1) This round consisted of 30 aptitude questions based on general aptitude and computer science fundamental subjects like operating system, dbms, c/c++, sql, computer networks. Around 300 students sat for this test and 41 students were shortlisted for the next coding ro
4 min read
Intuit Interview | Set 8 (On-Campus)
Intuit came to our college campus for placements. Shortlisted 13 students after written and then selected 4 students for Full Time Job. There were 3 coding questions and 21 (apti+puzzles) to be done in 90 minutes. Apti n puzzle questions were 5 marks each and coding questions were 100 marks each. On
5 min read
IBM Placement Paper | Logical Reasoning Set - 4
This is an IBM model placement paper on Logical Reasoning for placement preparation. This placement paper will cover logical reasoning questions that are asked in IBM recruitment drives and also strictly follows the pattern of questions asked in IBM interviews. It is recommended to solve each one of
8 min read