For the following problem:
The output/correct result is specified as:
Output: [3,9,20,null,null,15,7]
I'm not sure what that output actually represents. I tried to scan it by level . E.g 3 is the root, then its children are 9 and 20 (which does not work). So then what is the actual tree?
It's how the binary tree is represented.
Output is a list of nodes where for node i (starting from index 0), node 2*i+1 is its left child and node 2*i+2 is its right child. So if those nodes do not exist, the corresponding value in the list is represented as NULL.
In this case, node 0 has a value of 3, and its left child is shown in node 1 (Output[1]) with value 9, while its right child is shown in node 2 (Output[2]) with value 20.
However, node 2 (Output[2] with value 20) does not have any children so the values corresponding to its children (Output[3], Output[4]) are shown as Null.
Related
This is a question I got in an interview, and I'm still not fully sure how to solve it.
Let's say we have a tree of numbers, and we want to find the size of the largest connected region in the tree whose nodes have the same value. For example, in this tree
3
/ \
3 3
/ \ / \
1 2 3 4
The answer is 4, because you have a region of 4 connected 3s.
I would suggest a depth first search with a function that takes two inputs:
A target value
A start node
and returns two outputs:
the size of the subtree of node with values equal to the target value
the largest size of connected region within the subtree of node
You can then call this function with a dummy target value (e.g. -1) and the root node and it will return the answer in the second output.
In pseudocode:
dfs(target_value,start_node):
if start_node.value == target_value:
total = 1
best = 0
for each child of start_node:
x,m = dfs(target_value,child)
best = max(m,best)
total += x
return total,best
else
x,m = dfs(start_node.value,start_node)
return 0,max(x,m)
_,ans = dfs(-1, root_node)
print ans
Associate a counter with each node to represent the largest connected region rooted at that node where all the nodes are the same value. Initialize this counter to 1 for every node.
Run DFS on the tree.
When you back up from any node, if both nodes have the same value, add the child node's counter to the parent's counter.
When you're done, the largest counter associated with a node is your answer. You can keep track of this as you run the algorithm.
I want to caculate the height of a binary tree wihout using the algorithme that takes the maximum of the depths of each leaf.
This is the structure that I have on eache node
[content, left_son, right_son, father_node]
a list of arrays of size 4 that represents every node. the left_son, right_son, and father are respectively the indexes of the the left son node, the right son node and the father node in the list
This is indeed possible, but you have to rework your data structure a bit:
You can store a binary Tree in an array like this:
Store the value of the root node at index 0.
Store the left child of
a node at index 2*i+1, where i is the index of the current node;
right child goes at index 2*i+2.
If you do it like this
a node's parent is saved at index (i-1)/2.
your array needs the length 2^(h+1)-1, where h is the height of the tree.
So all you have to do ist keep track of the last "used" index in your array and use the above formula to calculate the height.
2^(h+1)-1 = l => h = ceil(ld(l+1))-1
whith l being the length of your array you effictively use and ld the logarithm with base 2.
Given a binary tree, whose root is located a treasure, and whose internal nodes can contain a dragon or does not contain anything, you are asked to design an algorithm that tells us the leaf of the tree whose path to the root has the lowest number of dragons. In the event that there are multiple paths with the same number of dragons, the algorithm will return that which is more to the left of all them. To do this, implement a function which gets a binary tree whose nodes store integers:
The root contains the integer 0, which represents the treasure.
The internal nodes contain the integer 1 to indicate that the node there is a dragon or the integer 2 to indicate that there is no dragon.
In each leaf stores an integer greater than or equal to 3 that cannot be repeated. and return the whole sheet to the path selected. The tree has at least one root node and a leaf node different from the root. For example, given the following tree (the second test case shown in the example), the algorithm return the integer 4.
I can not upload a picture of the tree of example, but someone tell me with words that I can do to go through all the branches, and to know which is the path with less dragons I'd appreciate it.
A greeting!
You want to think about these problems recursively: if you're at a parent node with...
no children you must have no dragon and a node counter, and you consider yourself to have 0 dragons and be the best node: you'd tell your parent that if asked
a left branch and/or a right branch, then you ask your children for their dragon-count and which node they consider best, and IF the left node reports a lesser or equal dragon count...
you take your best-node and dragon-count from it, ELSE
you take your best-node and dragon-count from the right node
then you add 1 to the dragon-count if your node's storing the integer 1
By starting that processing at the root node, you get the result for the entire tree.
This is the first algorithm that comes to mind. Assuming that you have an array that stores the values in nodes node_value[NODE_NUM], where NODE_NUM is the number of nodes in your tree, and you store index of childs of each node with the arrays left[NODE_NUM] and right[NODE_NUM], and your root will have index root_index. We will store information about the number of dragons in the path to root in the array dragon[NODE_NUM] So the algorithm pseudocode is:
# the recursive function itself
process(node_index):
n_left <- 0
if node_value[left[node_index]] = 1
n_left <- 1
n_right <- 0
if node_value[right[node_index]] = 1
n_right <- 1
dragon[left[node_index]] <- dragon[node_index] + n_left
dragon[right[node_index]] <- dragon[node_index] + n_right
process(left[node_index])
process(right[node_index])
# the number of dragons in path from root to root is, obviously, zero:
dragon[root_index] <- 0
# Call the function itself
process(root_index)
After that, in dragon we will have the number of dragons in the way to root from every nodes in tree. Now, all you have to do is to loop through all nodes and find the node that is a leaf and that its values is minimal:
min <- infinity
node_min <- unknown
for each node:
if node_value[node] >= 3:
if dragon[node] < min:
min <- dragon[node]
node_min <- node
return node_min
Now, the node_min is the node that has least dragons in the path to root.
So far i know that small value integers is placed at LHS and big value is placed at RHS. Can anyone give a good explanation. Thank you
Just to go over the background (skip this if you know it already):
A tree is a collection of nodes connected by edge with no loops allowed. The topmost node is called the root node. Nodes can have zero or more child nodes, which are nodes that extend downward from it. All nodes have exactly one parent node that extends upward from it (the root is the exception and has not parents). Allowing more than one parent would create loops, which are not allowed in trees.
A binary tree is a special type of tree where every node has at most two child nodes. All nodes in a binary tree have a value, a left pointer and a right pointer. The pointers point to the left and right child nodes, if they exist. If they don't exist, the pointers are NULL pointers don't point anywhere.
A binary search tree is a special type binary tree where the nodes are organized in a special way:
given any node, all nodes in its left subtree will have a lesser value
given any node, all nodes in its right subtree will have a greater value
Binary search trees are organized like this to allow for easy searching of values.
Now for the insertion algorithm...
Let's say we are given the number 3 to insert into the following tree:
6
/ \
4 9
/ \ /
2 5 8
All we need to do is start at the root and descend down the tree, going left if our new value less than the node value, and right if the our new value is greater. We stop when we find an empty space to insert out node.
So to insert the number 3...
start at the top node
3 is less than 6, so go left
3 is less than 4, so go left
3 is greater than 2, so go right
we've found empty space for a new node, so insert it here
6
/ \
4 9
/ \ /
2 5 8
\
3
The Insert() procedure can be defined recursively. Once we decide to move left or right, we can just focus on the subtree below the current node and forget about the rest of the tree.
In pseudocode:
Insert(Node root, int newValue)
if (root is empty)
Node N = new Node
N.value = newValue
else if (root.value < newValue)
Insert(root.left, newValue)
else if (root.value > newValue)
Insert(root.left, newValue)
I'm trying to write a function to remove a node from a binary tree. I haven't coded the function yet, and I am trying to think about the different conditions I should consider for removing a node. I am guessing that the possible conditions are:
The node has no children
The node has one child
The node has 2 children
In each of these cases what would be the algorithm to perform a delete function?
This is something you would find in any standard textbook about algorithms, but let's suppose you are interested in the unbalanced case (balanced trees usually performs some rebalancing operations called "rotations" after a removal) and you use the "obvious" datastructure (a tree_node structure that holds the value and two pointers to other tree_node):
No children: release the memory hold by the node and set the parent's child link that pointed to it as NULL;
One child: release the memory hold by the node and set the parent's child link that pointed to it as the address of its unique child;
Two children: this is indeed the "complicated" case. Find the rightmost node of the left child (or the leftmost node of the right child), take its value, remove it (it is "case 1", so it is easy and can be done recursively) and set the current node's value as the one of that node. This is O(tree_height) = O(n), but it is not a problem (at least in theory) because this would be neverthless the complexity of finding a node.
Does your tree have any additional properties?
Is it an AVL?
If not, there are some pretty obvious and straightforward ways to do what you want (which will depend on your data representation, as Vitalij said).
And if it is an AVL for example, there ALSO are some well known method for doing that (wikipedia will tell you more on that topic)
First task is to find whether node exists which will be done during search and rest of your conditions are correct.
Leaf node: set the parent's child (right/left) to NULL.
Has one child: Just set the child of the node to be deleted to its parent's child.
Has two children: Basically have to re-order the whole subtree here by pruning the subtree to by finding new children for the node to be deleted.
Assuming you are dealing with general binary trees, do the following,
Node has no child- ie it is a leaf : Conveniently delete it..
Node has one child - Make the parent of the node to be deleted parent of its child , then delete the node. ie, if A->Parent = B; C->Parent = A; and A has to be deleted, then 1. Make C->Parent = B; 2. Delete A;
Tricky one.... Yes, replacing the node to be deleted by the left most child of the right subtree work, or by the rightmost tree of the left subtree, either will do... because it can be seen like this,
When a node is deleted, it has to be replaced by a node which satisfies some properties...
Lets say if our binary tree represents sorted numbers (in increasing order) in inorder traversal, then the deleted node should be replaced by some node from either of its subtrees. That should be larger in value than the whole remaining left subtree, and smaller than the whole remaining right subtree (remaining means the subtree remaining after adjusting for the deleted node successfully). Only two such nodes exist, leftmost leaf of the right subtree, or the rightmost node of left one.
Hence, replacing the deleted node from either one suffices...!!
Delete the given keys one at a time from the binary search tree. Possible equal keys were inserted into the left branch of the existing node. Please note that the insertion strategy also affects how the deletion is performed
BinarySearchTree-Delete
Node Delete(Node root, Key k)
1 if (root == null) // failed search
2 return null;
3 if (k == root.key) // successful search
4 return DeleteThis(root);
5 if (k < root.key) // k in the left branch
6 root.left = Delete(root.left, k);
7 else // k > root.key, i.e., k in the right branch
8 root.right = Delete(root.right, k);
9 return root;
Node DeleteThis(Node root)
1 if root has two children
2 p = Largest(root.left); // replace root with its immediate predecessor p
3 root.key = p.key;
4 root.left = Delete(root.left, p)
5 return root;
6 if root has only left child
7 return root.left
8 if root has only right child
9 return root.right
10 else root has no children
11 return null
Node Largest(Node root)
1 if root has no right child
2 return root
3 return Largest(root.right)