Given parent node array, print out preorder traversal of the tree - data-structures

Given an unsorted node array where node is defined as:
Node { int id;
int parent_id;
string label;
}
Each node has its own unique id. parent_id identify its parent in the tree. The question is how to do an preorder traversal of the tree? (not necessarily a binary tree)
This is an interview question that has troubled me for several days. What I can think of is to use a hash map map<int,list<node> > where key is the parentid. Then I cannot go further. Should I build the tree from map and do a preorder traversal or if there is a good way to do it directly from the map? Then how? Any hint is appreciated!

So you need:
map<int, list<Node> > childMap;
map<int, Node> nodeMap;
You'll find a node that doesn't have a parent (parent_id = -1 or something), this is obviously the root. You call the below function for that node after setting up the maps above.
preOrder(int id)
{
process(nodeMap[id]);
foreach (Node node: childMap[id])
preOrder(node);
}

Related

Find the number of nodes in a general binary tree that can be searched using BST searching algorithm

First of all, we know that the searching algorithm of a BST looks like this:
// Function to check if given key exists in given BST.
bool search (node* root, int key)
{
if (root == NULL)
return false;
if (root->key == key)
return true;
if (root->key > key)
return search(root->left, key);
else
return search(root->right, key);
}
This searching algorithm is usually applied in a binary search tree. However, when it comes to a general binary tree, such algorithm may give us wrong results.
The following question has trapped me for quite a long time.
Given a general binary tree, count how many nodes in it can be found using the BST searching algorithm above.
Take the binary tree below as an example. The colored nodes are searchable, so the answer is 3.
Suppose the keys in a tree are unique, and we know the values of all the keys.
My thoughts
I have a naive solution in my mind, which is to call the searching algorithm for every possible key, and count how many times the function returns true.
However, I want to reduce the times of calling functions, and also to improve the time complexity. My intuition tells me that recursion can be useful, but I'm not sure.
I think for each node, we need the information about its parent (or ancestors), therefore I have thought about defining the binary tree data structure as follows
struct node {
int key;
struct node* left;
struct node* right;
struct node* parent; // Adding a 'parent' pointer may be useful....
};
I couldn't really figure out an efficient way to tell if a node is searchable, neither can I come up with one to find out the number of searchable nodes. Thus I came here to look for help. A hint will be better than a full solution.
This is my first time asking a question on Stack Overflow. If you think this post needs improvement, feel free to leave a comment. Thanks for reading.
To count the keys that can be found, you should traverse the tree and keep track of the range (low, high) that is implied by the path you took from the root. So when you go left from a node that has key 5, then you should consider that you cannot find any values any more that are greater than 5 (or equal, as that value is already accounted for). If that node's left child node has key 2, and you take a right, then you know that you cannot find any values any more that are less than 2. So your window has at that moment narrowed to (2, 5). If that window becomes empty, than it makes no sense to dig deeper in that direction of the tree.
This is an algorithm you can apply easily using recursion. Here is some code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct node {
int key;
struct node* left;
struct node* right;
} Node;
Node *create_node(int key, Node *left, Node *right) {
Node * node = malloc(sizeof(struct node));
node->key = key;
node->left = left;
node->right = right;
return node;
}
int count_bst_nodes_recur(Node *node, int low, int high) {
return node == NULL || node->key <= low || node->key >= high ? 0
: 1 + count_bst_nodes_recur(node->left, low, node->key)
+ count_bst_nodes_recur(node->right, node->key, high);
}
int count_bst_nodes(Node *node) {
return count_bst_nodes_recur(node, -INT_MAX, INT_MAX);
}
int main(void) {
// Create example tree given in the question:
Node *tree = create_node(1,
create_node(2,
create_node(4, NULL, NULL),
create_node(5, NULL, NULL)
),
create_node(6,
NULL,
create_node(7, NULL, NULL)
)
);
printf("Number of searchable keys: %d\n", count_bst_nodes(tree)); // -> 3
return 0;
}
The following property is very important for solving this question.
Any binary tree node which respects the BST properties will always be searchable
using BST Search Algorithm.
Consider the example you had shared.
.
Now, suppose
If you are searching for 1 => Then it will lead to success in the first hit. (Count =1)
For 2, it will search in the right subtree of 1. AT 6, no left subtree was found, hence not found.
For 6, search in the right subtree of 1. Match found! (Count =2)
Similarly for 7, search in the right subtree of 1 followed by a search in 6. Match found! (Count =3)
Now, the counter is incremented when all numbers from 0 to max(nodes) are searched in the list.
Another interesting pattern, you can see is that counter is incremented whenever node follows a BST Node property.
One of the important property is:
Root node's value is greater than all the root's left's values and less than all the root's right values.
For example, Consider node 7: it is to the right of 6 and right of 1. Hence a valid node.
With this in mind, the problem can be decomposed to Number of valid BST Nodes in a tree.
Solving this is quite straightforward. You try to use a Tree traversal from top to bottom and check if it is in increasing order. If it is not, there is no need to check its children. If it is, then add counter by 1 and check its children.

Binary tree Inorder traversal from only postorder traversal provided

I got a question in my coding challenge.
A complete binary tree is a binary tree where every node except the leaf node has two child nodes and the last level of the tree for an edge-height h has 2^h leaf-nodes.
Your task is simple, given the post-order traversal for a complete binary tree, print its in-order traversal.
The elements in the binary tree are of type character i.e. each node stores one character value.
Format of input / output
Input Format:
Only one string input denoting the postorder traversal.
Constraints:
1 <= input.length <= 1000
Output Format:
output one string that denotes the inorder traversal of the binary tree
Sample
Sample Input 0:
BCA
Sample Output 0:
BAC
I did have a full answer ready to go, but #EricWang beat me to the implementation. So here's a supplementary answer describing the process in more detail. Please accept his as the answer.
I'm going to use the post-order traversal DEBFGCA, as it's useful to consider slightly more nodes.
Because the tree is complete, for any given node we know that the the number of children on the left is the same as the number of children on the right. Therefore we can look at the post-order traversal DEBFGCA and know that it has the structure LLLRRRN, where L is the post-order traversal of the left subtree, R is the post-order traversal of the right subtree, and N is the node itself.
More generally, we know that the post-order traversal of the left subtree is characters 0 to (tree.length - 1)/2 - 1, and the post-order traversal of the right subtree is characters (tree.length -1)/2 - 1 to tree.length - 2. The node is the last character, at tree.length - 1.
Obviously, to change this to an in-order traversal, we just have to identify the left and right subtrees, change them to in-order traversal, and then return LLLNRRR. We can use recursion to convert the left and right subtrees to in-order.
So for example, start with DEBFGCA. We know the structure is LLLRRRN, so the left subtree is DEB, the right subtree is FGC, and the node is A. We want to turn DEB into in-order...
Process DEB. We know the left subtree is D, right is E, node is B. Both subtrees have length 1, so are leaves. No further recursion required. Return LNR, which is DBE.
Process FGC. As before, return FCG.
Now we know the in-order left is DBE and right is FCG. Return LLLNRRR, which is DBEAFCG.
You can do it dynamically, with recursion.
Mechanism
Split a tree to 3 parts: left, right, root.
Re-join them in order: left, root, right.
Split recursively, till the length of subtree is one.
Code - in Java
PostToInOrder.java
public class PostToInOrder {
public static String convert(String post) {
checkPerfect(post); // check whether tree is perfect,
return convertInner(post);
}
private static String convertInner(String post) {
int len = post.length();
if (len == 1) return post; // base case,
String left = post.substring(0, len >> 1); // left of post,
String right = post.substring(len >> 1, len - 1); // right of post,
char root = post.charAt(len - 1); // root of post,
return convertInner(left) + root + convertInner(right);
}
private static void checkPerfect(String tree) {
if (!isPerfect(tree)) throw new IllegalArgumentException("input is not perfect tree, size: " + tree.length());
}
private static boolean isPerfect(String tree) {
int len = tree.length();
if (len < 1) return false;
while (len != 0) {
if ((len & 1) == 0) return false;
len >>= 1;
}
return true;
}
}
PostToInOrderTest.java:
(Unit test, via TestNG)
import org.testng.Assert;
import org.testng.annotations.Test;
public class PostToInOrderTest {
#Test
public void test() {
Assert.assertEquals(PostToInOrder.convert("BCA"), "BAC");
Assert.assertEquals(PostToInOrder.convert("02146538A9CEDB7"), "0123456789ABCDE");
Assert.assertEquals(PostToInOrder.convert("A"), "A"); // single element,
}
#Test(expectedExceptions = IllegalArgumentException.class)
public void test_invalid_empty() {
PostToInOrder.convert("");
}
#Test(expectedExceptions = IllegalArgumentException.class)
public void test_invalid_notPerfect() {
PostToInOrder.convert("AB");
}
}
BTW:
The tree described in question is a perfect binary tree.
It's a sub type of complete binary tree.
A complete tree is not necessary perfect, its last level could lack of some leaves.
e.g AB is a complete tree, but not perfect tree.

Rebalancing an arbitrary BST?

Reference:
I was asked this question #MS SDE interview, 3rd round. And it's not a homework problem. I also gave it a thought and mentioning my approach below.
Question:
Modify a BST so that it becomes as balanced as possible. Needless to mention, you should do it as efficient as possible.
Hint:
Interviewer said that this is a logical question, if you think differently you will get the answer. No difficult coding involved.
--> Having said that, I do not think he was expecting me to point to AVL/RB Trees.
My Solution:
I proposed that, I would do inorder traversal of tree, take middle element as root of new tree(lets call it new root). Then go to the left part of middle element, take its middle element as root of left subtree of tree rooted new root. Similarly do for right part.
Doing this recursively will give the optimal balanced BST.
Why I am posting it here:
But he was not satisfied with the answer :( So, is there really a way of doing this w/o going for weights/RB coloring strategy, or was he just fooling around with me?
Please put in your expert thoughts.
Duplicate? No!
I know there is this question but the solution proposed by requester is too complicated, and other one talks about AVL trees.
You might want to look into the Day-Stout-Warren algorithm, which is an O(n)-time, O(1)-space algorithm for reshaping an arbitrary binary search tree into a complete binary tree. Intuitively, the algorithm works as follows:
Using tree rotations, convert the tree into a degenerate linked list.
By applying selective rotations to the linked list, convert the list back into a completely balanced tree.
The beauty of this algorithm is that it runs in linear time and requires only constant memory overhead; in fact, it just reshapes the underlying tree, rather than creating a new tree and copying over the old data. It is also relatively simple to code up.
Hope this helps!
"Balanced as possible" = complete (or full) binary tree1. You cannot get more balanced that it.
The solution is simple - build an "empty" complete binary tree, and iterate the new tree and the input tree (simultaneously) in inorder-traversal to fill the complete tree.
When you are done, you have the most balanced tree you can get, and time complexity of this approach is O(n).
EDIT:
This should be done following these steps:
Build a dummy complete tree with n nodes. All the values to each
node will be initialized to some garbage value.
Create two iterators: (1) originalIter for the original tree, (2) newIter for the new (initialized with garbage) tree. Both iterators will return elements in in-order traversal.
Do the following to fill the tree with the values from the original:
while (originalIter.hasNext()):
newIter.next().value = originalIter.next().value
(1) (From Wikipedia): A complete binary tree is a binary tree in which every level, except possibly the last, is completely filled, and all nodes are as far left as possible
The DSW algorithm can solve this is O(n) time. The algorithm goes as follows:
1] Using right-rotation operations, turn the tree into a linked list
(a.k.a. backbone or vine)
2] Rotate every second node of the backbone about its parent to turn
the backbone into a perfectly balanced BST.
Reference
This will convert your normal BST into a balanced BST with minimum possible height in O(n). First, save all your nodes sorted into a vector. Then, the root is the mid element and recursively build a tree from 0 to mid-1 as its left and build a tree from mid+1 to vector.size()-1 as its right child. After all these steps root keeps the balanced BST with the min-height.
import java.util.Vector;
public class ConvertBSTIntoBalanced {
public static void main(String[] args) {
TreeNode node1 = new TreeNode(1);
TreeNode node2 = new TreeNode(2);
TreeNode node3 = new TreeNode(3);
TreeNode node4 = new TreeNode(4);
node1.right = node2;
node2.right = node3;
node3.right = node4;
ConvertBSTIntoBalanced convertBSTIntoBalanced = new ConvertBSTIntoBalanced();
TreeNode balancedBSTRoot = convertBSTIntoBalanced.balanceBST(node1);
}
private void saveNodes(TreeNode node, Vector<TreeNode> nodes) {
if (node == null)
return;
saveNodes(node.left, nodes);
nodes.add(node);
saveNodes(node.right, nodes);
}
private TreeNode buildTree(Vector<TreeNode> nodes, int start, int end) {
if (start > end)
return null;
int mid = (start + end) / 2;
TreeNode midNode = nodes.get(mid);
midNode.left = buildTree(nodes, start, mid - 1);
midNode.right = buildTree(nodes, mid + 1, end);
return midNode;
}
public TreeNode balanceBST(TreeNode root) {
Vector<TreeNode> nodes = new Vector<>();
saveNodes(root, nodes);
return buildTree(nodes, 0, nodes.size() - 1);
}
public class TreeNode {
public Integer val;
public TreeNode left;
public TreeNode right;
public TreeNode(Integer x) {
val = x;
}
}
}
I hope it helps.

How to verify if a given tree is a Binary Search Tree or not [duplicate]

This question already has answers here:
How do you validate a binary search tree?
(33 answers)
Closed 8 years ago.
I wanted to know if a given binary tree is a binary search tree or not.
I don't know How to do that?
The only thing I know is that the inorder traversal of BST will gives you ascending order output.
So, is this the only condition we need to verify or is there anything else we are suppose to check.
In case if there are some other necessary conditions to be checked, What are they? and why those conditions are necessary to be checked? Because, I think, INORDER traversal itself can tell you easily if the given tree is BST or not.
Yes, if inorder traversal of the tree gives you a strictly monotonic list of values that is sufficient to determine that the tree is a BST.
By definition of Binary search tree, if every node of the binary tree satisfy the following conditions then it is a Binary Search Tree:
The left subtree of a node should contain only nodes with keys less than the node’s key
The right subtree of a node should contain only nodes with keys greater than the node’s key
Both the left and right subtrees must also be binary search trees.
All the above conditions are verified if the inorder traversal is in ascending order.
Actually - it is not enough to just do an in order traversal - you also need to verify that each node's value follows the rules of the tree. In the case of a BST, the left child value is less than the node value and the right child value is greater than the node value. Here is a recursive example in Java.
private static boolean isBST(Node current, Comparable more, Comparable less) {
if (current == null)
return true;
if (less != null && current.value.compareTo(less) > 0)
return false;
if (more != null && current.value.compareTo(more) < 0)
return false;
return isBST(current.left, more, current.value) &&
isBST(current.right, current.value, less);
}
public static boolean isBST(BinarySearchTree tree) {
return isBST(tree.getRoot(), null, null);
}
While doing In-Order traversal, we can keep track of previously visited node
Code:
bool isBST(struct node* root)
{
static struct node *prev = NULL;
// traverse the tree in inorder fashion and keep track of prev node
if (root)
{
if (!isBST(root->left))
return false;
// Allows only distinct valued nodes
if (prev != NULL && root->data <= prev->data)
return false;
prev = root;
return isBST(root->right);
}
return true;
}
A simple but elegant recursive solution in Java:
public static boolean isBST(TreeNode node, int leftData, int rightData)
{
if (node == null) return true;
if (node.getData() > leftData || node.getData() <= rightData) return false;
return (isBST(node.left, node.getData(), rightData)
&& isBST(node.right, leftData, node.getData()));
}
The initial call to this function can be something like this:
if (isBST(root, Integer.MAX_VALUE, Integer.MIN_VALUE))
System.out.println("This is a BST.");
else
System.out.println("This is NOT a BST!");
Essentially we keep creating a valid range (starting from [ MIN_VALUE, MAX_VALUE]) and keep shrinking it down foe each node as we go down recursively.
Source: http://exceptional-code.blogspot.com/2011/08/binary-search-trees-primer.html

Populate the data field of all the nodes of the tree

A node of a binary tree has two pointers, 'left' and 'right', and two data fields, 'leftcount' and 'rightcount'. 'leftcount' specifies the number of nodes in the left subtree of the node, and 'rightcount' specifies the number of nodes in the right subtree of the node. Write an algorithm to populate the data fields of all the nodes of the tree.
I was asked this question in an interview. I came up with a solution which was based on a postorder traversal of the tree. Can someone please guide me on this.
This should work (I believe):
int populateCounters(Node* node) {
if(node == NULL) return 0;
node->leftCount = populateCounters(node->left);
node->rightCount = populateCounters(node->right);
return node->leftCount + node->rightCount + 1;
}

Resources