Finding highest value within an n -ary tree - recursion

I have an arraylist which is linked in a tree structure (a family tree to be precise). Each node is an object containing a generation field. I would like to find the leaf with the highest generation within the tree. I tried this:
private int findHighestLeafGeneration(FamilyMember node, int gen){
if(node.getChildren().isEmpty()){
return gen;
}
for(int i = 0; i < node.getChildren().size(); i++){
gen = findHighestLeafGeneration(node.getChild(i), node.getChild(i).getGeneration());
}
return gen;
}
I call the method like this:
findHighestLeafGeneration(node, node.getGeneration());
What this is supposed to do is take a member of the family tree (a node) and print all the descendants for that member. My PrintDescendants method requires the number of generations to print.
The above is a little buggy however. It gets the leaf generation then returns and overwrites the leafs generation with the parent nodes generation. Any clues why?

Do this:
private int findHighestLeafGeneration(FamilyMember node) {
int gen = node.getGeneration();
for(int i = 0; i < node.getChildren().size(); i++){
int highestChild = findHighestLeafGeneration(node.getChild(i));
if(highestChild > gen) {
gen = highestChild;
}
}
return gen;
}

Related

Connect All Siblings in Binary Tree Using Pointers

Problem: https://www.educative.io/m/connect-all-siblings
I'm attempting to connect all sibling nodes by creating a dummy node and set it's next to the node that we're currently visiting by using a next pointer, but after executing the code:
public static void populate_sibling_pointers(BinaryTreeNode root) {
if(root == null) return;
Queue<BinaryTreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()){
int size = q.size();
BinaryTreeNode dummy = new BinaryTreeNode(0);
for(int i = 0; i < size; i++){
BinaryTreeNode cur = q.poll();
dummy.next = cur;
dummy = dummy.next;
if(cur.left!=null){
q.offer(cur.left);
}
if(cur.right!=null){
q.offer(cur.right);
}
}
}
}
I still failed to pass some test but I'm not sure what I did wrong here.
Any help is appreciated!
Two issues:
You should create a new dummy node only once. By creating a new one at every iteration of the while loop, you break the chain of next references. So the creation of that node should happen before the while loop.
The last node in the next chain should have its next set to null.
Here is the corrected code:
class connectSiblings{
public static void populate_sibling_pointers(BinaryTreeNode root) {
if(root == null) return;
Queue<BinaryTreeNode> q = new LinkedList<>();
q.offer(root);
BinaryTreeNode dummy = new BinaryTreeNode(0);
while(!q.isEmpty()){
int size = q.size();
for(int i = 0; i < size; i++){
BinaryTreeNode cur = q.poll();
dummy.next = cur;
dummy = dummy.next;
if(cur.left!=null){
q.offer(cur.left);
}
if(cur.right!=null){
q.offer(cur.right);
}
}
}
dummy.next = null;
}
}
You can further optimise this code by replacing the use of the LinkedList with the actual linked list you are building with the next references: when a layer of the tree has been correctly wired with next references, you can iterate that section of that linked list to find and wire the nodes of the next layer, which then can serve as linked list for the next layer, ...etc.

Breadth first traversal of arbitrary graph with minimal memory

I have an enormous directed graph I need to traverse in search for the shortest path to a specific node from a given starting point. The graph in question does not exist explicitly; the child nodes are determined algorithmically from the parent nodes.
(To give an illustration: imagine a graph of chess positions. Each node is a chess position and its children are all the legal moves from that position.)
So I have a queue for open nodes, and every time I process the next node in the queue I enqueue all of its children. But since the graph can have cycles I also need to maintain a hashset of all visited nodes so I can check if I have visited one before.
This works okay, but since this graph is so large, I run into memory problems. All of the nodes in the queue are also stored in the hashset, which tends to be around 50% of the total number or visited nodes in practice in my case.
Is there some magical way to get rid of this redundancy while keeping the speed of the hashset? (Obviously, I could get rid of the redundancy by NOT hashing and just doing a linear search, but that is out of the question.)
I solved it by writing a class that stores the keys in a list and stores the indices of the keys in a hashtable. The next node "in the queue" is always the the next node in the list until you find what you're looking for or you've traversed the entire graph.
class IndexMap<T>
{
private List<T> values;
private LinkedList<int>[] buckets;
public int Count { get; private set; } = 0;
public IndexMap(int capacity)
{
values = new List<T>(capacity);
buckets = new LinkedList<int>[NextPowerOfTwo(capacity)];
for (int i = 0; i < buckets.Length; ++i)
buckets[i] = new LinkedList<int>();
}
public void Add(T item) //assumes item is not yet in map
{
if (Count == buckets.Length)
ReHash();
int bucketIndex = item.GetHashCode() & (buckets.Length - 1);
buckets[bucketIndex].AddFirst(Count++);
values.Add(item);
}
public bool Contains(T item)
{
int bucketIndex = item.GetHashCode() & (buckets.Length - 1);
foreach(int i in buckets[bucketIndex])
{
if (values[i].Equals(item))
return true;
}
return false;
}
public T this[int index]
{
get => values[index];
}
private void ReHash()
{
LinkedList<int>[] newBuckets = new LinkedList<int>[2 * buckets.Length];
for (int i = 0; i < newBuckets.Length; ++i)
newBuckets[i] = new LinkedList<int>();
for (int i = 0; i < buckets.Length; ++i)
{
foreach (int index in buckets[i])
{
int bucketIndex = values[index].GetHashCode() & (newBuckets.Length - 1);
newBuckets[bucketIndex].AddFirst(index);
}
buckets[i] = null;
}
buckets = newBuckets;
}
private int NextPowerOfTwo(int n)
{
if ((n & n-1) == 0)
return n;
int output = 0;
while (n > output)
{
output <<= 1;
}
return output;
}
}
The old method of maintaining both an array of the open nodes and a hashtable of the visited nodes needed n*(1+a)*size(T) space, where a is the ratio of nodes_in_the_queue over total_nodes_found and size(T) is the size of a node.
This method needs n*(size(T) + size(int)). If your nodes are significantly larger than an int, this can save a lot.

Having problem in conversion from Recursive solution to DP

Given a Binary Tree of size N, find size of the Largest Independent Set(LIS) in it. A subset of all tree nodes is an independent set if there is no edge between any two nodes of the subset. Your task is to complete the function LISS(), which finds the size of the Largest Independent Set.
I came up with this recursive solution.
int rec(struct Node *root,bool t)
{
if(root==NULL)
return 0;
if(t==true)
{
return max(1+rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
}
else
{
return max(rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
}
}
int LISS(struct Node *root)
{
int x,y;
y=rec(root,true);
return y;
}
To solve this problem via DP, I modified the code as follows, but then it gives wrong answer.
It doesn't even work with Binary tree with distinct elements.
map<int,int> mm;
int rec(struct Node *root,bool t)
{
if(root==NULL)
return 0;
if(mm.find(root->data)!=mm.end())
return mm[root->data];
if(t==true)
{
mm[root->data]=max(1+rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
return mm[root->data];
}else
{
mm[root->data]=max(rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
return mm[root-s>data];
}
}
int LISS(struct Node *root)
{
//Code here
mm={};
int y=0;
y=rec(root,true);
return max(x,y);
}
What's the mistake?
You have two states in your function but you are memoizing only one state. Let's say for root x,
rec(x,true) = 5 and
rec(x,false) = 10 .
You calculated the rec(x, true) first and saved it in your map "mm" as mm[x] = 5.
So when you are trying to get the value of rec(x, false) it is getting the value of rec(x, true) which is 5.

What is the logic to recursively subdivide an octree?

I am trying to recursively subdivide an octree and I am struggling with the logic of how to allow each node to be visited, but preventing an infinite recursion.
It only seems to be visiting the first node, and then stopping and I understand why it is doing this, but I'm not sure how to fix it.
I am defining a maxDepth of 2, and a currentDepth which is supposed to increment once all child nodes have been subdivided. I initially pass in the root node and it should recursively go through until the max depth is reached.
This is what I have so far, where depth 1 works fine and it gets subdivided, but when I want a maxDepth of 2, it will only visit the first node and leave the rest.
Here is the code I am using to subdivide.
private void subdivideNode(OctreeNode node)
{
if (currentDepth >= maxDepth) return;
node.subdivide();
currentDepth++;
for (int i = 0; i < node.children.Length; i++)
{
subdivideNode(node.children[i]);
}
}
The subdivide method in OctreeNode creates the 8 octants of a given node
Figured it out by using
private void subdivideNode(OctreeNode node, int depth)
{
if (depth == maxDepth) return;
node.subdivide();
for (int i = 0; i < node.children.Length; i++)
{
subdivideNode(node.children[i], depth + 1);
}
}

Recursive method to get the number of occurences of an element in a binary tree

Hi. I am having trouble writing this method (in the photo) in a recursuve format. The method gets the amount of occurences of a given element in the binary search tree.
To solve this recursively, I was trying to implement it with a private helper method of the same name, like this:
public int count(){
count = 0;
if (root == null)
return count;
return count (root.getInfo());
private int count(T element){
(Basically the same code you see in the photo)
}
but I ended up with overflow errors. Would you mind taking a look and telling me how I can structure this method recursively?
Cheers, and thanks.
A tentative implementation may looks like this.
public int count(T element, T root){
if(element == null) {
return 0;
}
int count = 0;
int compare = element.compareTo(root.getInfo());
if(compare == 0){
count++;
}
count += count(element, root.getLeft());
count += count(element, root.getRight());
return count;
}
count(item, root);

Resources