Iterations to delete node and its children in a binary tree - data-structures

Example Tree image
Given a binary tree and pointer to a node (which is present) in tree, assume we have parent pointers. I have to find the number of iterations to delete the adjacent nodes and subsequent adjacent nodes of that deleted nodes. Here deleting means setting some flag, node -> burn. I wont delete the node.
Example :
1
/ \
2 3
/ \ / \
4 5 6 7
/ /
8 9
/
10
and given node in tree is 4,
The burned nodes in each iteration
In iteration 1:
For node 4: 4,8,2 (8 is the child node, 2 is parent of 4 , these are the adjacent nodes of 4).
In iteration 2:
For node 8: 10 will be burned. (4 is already burned)
For node 2: 5 and 1 will be burned.
This continues... , hence i have to find the number of iterations required to burn all nodes.

Not efficient but I think it will work:
Maintain a queue for the next nodes to be considered for deletion. And before deleting a node's adjacent nodes check whether they already have burn flag set.
Also, every time when you remove an item from queue:
check if all the nodes are burned or not (for this you can maintain a
Hash for faster access)
increment iteration count(which will be your result)

Related

Breadth First Search vs Depth First Search

Can anybody give a simple explanation on BFS and DFS?
I want to understand when to prefer BFS over DFS.
BFS and DFS are both graph traversing algorithms, the difference between them is the way each algorithm traverses the graph.
DFS, Imagine you have the following graph and we want to start traversing from node 1:
1
/ \
2 3
/ \ \
4 5 6
DFS means Depth first search, so it will traverse the graph in this way:
start from node 1 then look for its children. It finds node 2.
go to node 2 then look for its children. It finds node 4.
go to node 4 then it finds that it has no children.
go Up to node 2 again and see its other children. It finds node 5.
go to node 5 then it find that it has no children.
go up again to node 2 and find out that it has no more children.
go up to node 1 then look for its children. It finds node 3.
go to node 3 then look for its children. It find node 6.
go to node 6 and find out that it has no children.
go up to node 3 and find out that it has no more children.
go up to node 1 and find out that it has no more children, hence the graph traversal has finished at this point.
If you note here how this algorithm goes in depth first, so once it found that node 2 is a child of node 1 it went for it and started looking for its children without caring about the rest of children of node 1 (node 3) at this point of time, then after going to deepest possible node (nodes 4, 5) it started to go Up looking for the rest of children of node 1.
On the other hand, consider we want to traverse the same graph using BFS algorithm. When using BFS you start thinking of graph nodes as levels, each level is closer than the level after it relative to the node you start traversing from. which means:
1 (level 0)
/ \
2 3 (level 1)
/ \ \
4 5 6 (level 2)
So traversing the graph will be:
start from node 1 then look for its children (nodes 2, 3) [the next level].
traverse nodes of level 1 (2, 3) and look for their children (nodes 4, 5, 6) [the next level].
traverse nodes of level 2 (4, 5, 6) and look for this children (no children) [no next level].
then graph traversal ends at this point.
You can realize here that the direct children of a node (the next level) are always the closest nodes to it, and hence the advantage of using BFS over DFS is that it can guarantee for you that you reach from node x to node y using the shortest path possible.
But be aware that BFS algorithm can't find you the shortest path for all types of graph. The graph I mentioned in this example is unweighted graph (a graph in which all edges/paths are the same). If your graph is weighted (edges/paths have weights and not the same) then you have to use another algorithm that takes this into consideration (like Dijkstra).

How to count the maximum number of times any node has been visited while traveling through a tree several times?

We travel through a given tree (not binary) several times. How do we calculate the most number of times any node in the tree has been visited?
For example: in the tree:
1
/ \
2 3
/ \
4 5
Suppose we are told to travel 2 times, from 2 to 3, then 5 to 3. The travel paths will be (2->1->3 and 5->3). The maximum number of times a node has been visited is 2 (the node is 3). All travels are independent from each other. A given travel starts from a given node A and ends at B.
How to efficiently travel (if we even need to) in order to calculate that, considering that we have over 50,000 nodes and 75,000 paths to cover (like 2 to 3 and 3 to 4 in the example)?
Based on what you are saying, the answer is the amount of children that node has...
Also in your example, going off what you have said, both 1 and 3 are visited the most.
In your example each node is only going to get visited once. The only way you could get multiple visits to one node would be with a tree like:
1 3
\ /
2
Edit:: the most efficient way of traversing is if you have a perfect binary tre
4
2 6
1 3 5 7
Where the max depth is number of ((log base 2 of (number of nodes + 1)) + 1) rounded down
Why not store the travel count of each node separately?
Maintain a HashMap<Node, long> keeping track of how many times each node has been visited.
Then maintain a TreeMap<long, List<Node>> that is keyed on count and contains the list of node whose count it is representing.
This way, the TreeMap's first would contain all the nodes that have the highest count, because there can definitely be more than one node with that highest visit count.
All you now need to do is add bookkeeping code for properly updating the two maps whenever a node is visited as part of a tree traversal.
There's an XY problem here.
Your question states you want to store number of node visits. What you really want though is an efficient traversal strategy.
You have options here. Since the edges are bi-directional the best strategy IMO would be a bi-directional search.
But the search strategy itself is a toss up.
Consider a slightly more elaborate tree as
1 -> 2,3,4; 2 -> 5,6,7; 3->8,9; 4->10,11; 10 -> 12,13. If you have an efficient path from 5 to 4 It doesn't mean you can just start from there to find an efficient path from 5 to 13 because you don;t 13 comes under 4 unless you've already found an efficient path from 4 to 13.
So I would suggest memoizing your traversals in a dictionary of the form <Node Pair>: [Traversal list]
Where you start at a target node and perform a Breadth first search. and each time you visit a node, examine your memoization structure if there exists a an entry for <curnode,targetnode> in the dictionary. If there exists an entry, you are done. If not proceed to the current node's sibling or child.
CAVEAT: THIS IS UNDER THE ASSUMPTION THAT ALL NODES HAVE ONLY 1 PARENT AND CYCLES DON'T HAPPEN
I think people are miss understanding the question. He/she wants to ask which node is visited max number of times given x number of travel. So from his tree edges are {(2-1)(1-3)(3-4),(3-5)} now for example we are traveling in following paths{(1,5), (2,4), (1,3), (1,2), (1,3), (4,5)}. So this example 3 visited 5 times, 1 visited 4 times and so on.
Since it is a tree there is only one path exist from one node to another. Find paths for all combination of nodes in DP way and store it.
Then count for each visit. I know there is more efficient way for counting but cannot think of it right now.

Deleting a node in a binary tree having children

If we have to delete a node from a binary tree, how should we handle the children of the node being deleted. E.g. in this tree:
100
/
10
/ \
5 20
where 100 is the root node, 10 is left child of 100, 5 is left child of 10 and 20 is right child of 10. So after deleting 10, what will happen to 5 and 20?
It is your choice if what should you do after deleting.You would probably want to move one of the child upward on some so certain criteria. Either of of Child will take place of parent.
delete node in Binary Search Tree.
delete node in AVL.
Heapify in Heapsort.
And more.
So it is always a choice you have to take to solve for objective.

How many leaves are in a given heap and its level

I have a question and it goes like this:
There is a Max heap binary tree.
Let's assume that in the Heap there are (2^2017)-2017 nodes at the bottom-most level.
A)How many levels are there in the heap?
B)What are the number of the Leaves in the heap?
Thanks
A full binary heap that has 2x nodes at the bottom-most level has (x+1) levels. Consider this heap:
1
2 3
4 5 6 7
It has 4 (22) nodes at the bottom level, and 3 levels.
If the bottom level is full, then the number of leaf nodes is the same as the number of nodes on the bottom level.
In your case, the bottom level has (22017)-2017 leaf nodes. We know that the maximum number of nodes possible on this level is 22017 (because maximum is always a power of 2). And we also know, from the example above, that there are 2018 levels in the tree.
The number of leaf nodes, however, is not (22017)-2017. Consider this heap:
1
2 3
4 5 6 7
8 9
It has two leaf nodes at the bottom level, and three leaf nodes at the level above the bottom level (5, 6, and 7).
I think you'll find that in your case, the number of leaf nodes is (22017)-2017 + 2017/2. The 2017/2 is the number of leaf nodes on the level above.

How to build binary tree knowing only which nodes are connected?

I have to build a binary tree but i don't know which node is parent, left child, or right child. I only know which nodes are connected. Example: for input like this:
6 4
5 7
9 7
1 5
10 4
3 4
2 6
7 8
5 6
(from 1 there is always one path) the tree should looks like that:
One the input i have also given number of nodes. Any ideas, tips?
From the list of the edges, one can easily create a tree.
You can find which are the leaf nodes, just search which nodes are appearing only in one edge.
But, it is not possible to know which of the leaf nodes is the head of the tree.
In a tree structure it is possible to choose any leaf, choose it as the head, and reorder the tree, and it'll be a valid tree.
There is also the issue of tree isomorphism, you can swap the right and left sub-trees to get a valid tree.
To summarize, from this list you can get 6 heads and in each 4 possible swaps, so in total 24 different valid trees.

Resources