Print Specific nodes at a every level calculated by a given function - java

In an interview, i was given a function:
f(n)= square(f(n-1)) - square(f(n-2)); for n>2
f(1) = 1;
f(2) = 2;
Here n is the level of an n-array tree. f(n)=1,2,3,5,16...
For every level n of a given N-Array I have to print the f(n) node at every level. For example:
At level 1 print node number 1 (i.e. root)
At level 2 print node number 2 (from left)
At level 3 print node number 3 (from left)
At level 4 print node number 5... and so on
If the number of nodes(say nl) at any level n is less than f(n), then have to print node number nl%f(n) counting from the left.
I did a basic level order traversal using a queue, but I was stuck at how to count nodes at every level and handle the condition when number of nodes at any level n is less than f(n).
Suggest a way to proceed for remaining part of problem.

You need to perform Level Order Traversal.
In the code below I am assuming two methods:
One is getFn(int level) which takes in an int and returns the f(n) value;
Another is printNth(int i, Node n) that takes in an int and Node and beautifully prints that "{n} is the desired one for level {i}".
The code is simple to implement now. Comments explain it like a story...
public void printNth throws IllegalArgumentException (Node root) {
if (root == null) throw new IllegalArgumentException("Null root provided");
//Beginning at level 1 - adding the root. Assumed that levels start from 1
LinkedList<Node> parent = new LinkedList<>();
parent.add(root)
int level = 1;
printNth(getFn(level), root);
//Now beginning from the first set of parents, i.e. the root itself,
//we dump all the children from left to right in another list.
while (parent.size() > 0) { //Last level will have no children. Loop will break there.
//Starting with a list to store the children
LinkedList<Node> children = new LinkedList<>();
//For each parent node add both children, left to right
for (Node n: parent) {
if (n.left != null) children.add(n.left);
if (n.right != null) children.add(n.right);
}
//Now get the value of f(n) for this level
level++;
int f_n = getFn(level);
//Now, if there are not sufficient elements in the list, print the list size
//because children.size()%f(n) will be children.size() only!
if (children.size() < f_n) System.out.println(children.size());
else printNth(level, children.get(f_n - 1)); //f_n - 1 because index starts from 0
//Finally, the children list of this level will serve as the new parent list
//for the level below.
parent = children;
}
}

Added solution here
I have used queue to read all nodes at a particular level, before reading the nodes checking if given level(n) is equal to current level then checking size of the queue is greater than f(n) then just read f(n) nodes from queue and mark it as deleted otherwise perform mod operation and delete the node nl%f(n).

Related

Finding the number of nodes at each level during bfs

You have been given a Tree consisting of N nodes. A tree is a fully-connected graph consisting of N nodes and N−1 edges. The nodes in this tree are indexed from 1 to N. Consider node indexed 1 to be the root node of this tree. The root node lies at level one in the tree. You shall be given the tree and a single integer x . You need to find out the number of nodes lying on level x.
Input Format
The first line consists of a single integer N denoting the number of nodes in the tree. Each of the next n−1 lines consists of 2 integers a andb denoting an undirected edge between node a and node b. The next line consists of a single integer x.
Output Format
You need to print a single integers denoting the number of nodes on level x.
below is the code snippet i wrote and its not correct. Please help me find the error.
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;
public class LevelNodes {
public static ArrayList[] adj;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
boolean[] visites = new boolean[N];
ArrayList[] adj = new ArrayList[N];
for(int j=0;j<N;j++){
adj[j] = new ArrayList();
}
for(int i = 0;i < (N-1) ;i++){
int a = sc.nextInt();
int b = sc.nextInt();
adj[a-1].add(b);
adj[b-1].add(a);
}
int level = sc.nextInt();
int counter = 0;
LinkedList list = new LinkedList();
list.add(1);
counter++;
while(!list.isEmpty()){
int n = (Integer) list.poll();
for(int x = 0; x< adj[n-1].size();x++){
list.add(adj[n-1].get(x));
}
counter++;
if(counter == level){
System.out.println(list.size());
break;
}
}
}
}
There are a number of problems in your code:
The first problem is that your code might not terminate. This is because you are adding both edges u->v and v->u to your adjacency list. So whenever you poll u from the list and add its neighbors, you are going to add v to the list. Likewise, whenever you poll v and add its neighbors, you are going to add back u to the list. You need to maintain a boolean array visited and set visited[u]=true whenever you add u to the list. This way you can add only unvisited nodes to your scan list.
Another major problem is in the while loop. You are incrementing the level counter variable counter++; whenever you visit a new node. Consider the tree below and assume we need to find the number of nodes at level 2 (the last level).
1
/ \
2 3
/ \ / \
4 5 6 7
Initially your list contains 1 and counter=1. In the first iteration, you poll 1 from the list and add its neighbors: 2 and 3. At this stage, counter=2. In the next two iterations, you are going to remove 2 then 3 from the list, add their neighbors, and increment counter each time. So by the time you reach the second level, counter would be equal to 4. The If statement would never be executed.
To fix this, you have to increment counter iff you are done processing all the node at the current level. A simple (untested) way to do that is to use a second temporary list to hold the neighbors of all the nodes at the current level. Then, whenever the original list is empty, you know that you have processed all the nodes at the current level. Here, you increment counter and move all the nodes from the temporary list to the main list.
while(!list.isEmpty()){
int n = (Integer) list.poll();
for(int x = 0; x< adj[n-1].size();x++){
tmpList.add(adj[n-1].get(x));
}
if(list.isEmpty()) {
if(counter == level){
System.out.println(tmpList.size());
break;
}
list.addAll(tmpList);
tmpList.clear();
counter++;
}
}

Print random element from binary tree in O(logn)

Given a binary tree with TreeNode like:
class TreeNode {
int data;
TreeNode left;
TreeNode right;
int size;
}
Where size is the number of nodes in the (left subtree + right subtree + 1).
Print a random element from the tree in O(logn) running time.
Note: This post is different from this one, as it is clearly mentioned that we have a size associated with each node in this problem.
PS: Wrote this post inspired from this.
There is an easy approach which gives O(n) complexity.
Generate a random number in the range of 1 to root.size
Do a BFS or DFS traversal
Stop iterating at random numbered element and print it.
For improving the complexity, we need to create an ordering of our own where we branch at each iteration instead of going sequentially as in BFS and DFS. We can use the size property of each node to decide whether to traverse through the left sub-tree or right sub-tree. Following is the approach:
Generate a random number in the range of 1 to root.size (Say r)
Start traversing from the root node and decide whether to go to left sub-tree, right-subtree or print root:
if r <= root.left.size, traverse through the left sub-tree
if r == root.left.size + 1, print the root (we have found the random node to print)
if r > root.left.size + 1, traverse through the right sub-tree
Essentially, we have defined an order where current node is ordered at (size of left subtree of current) + 1.
Since we eliminate traversing through left or right sub-tree at each iteration, its running time is O(logn).
The pseudo-code would look something like this:
traverse(root, random)
if r == root.left.size + 1
print root
else if r > root.left.size + 1
traverse(root.right, random - root.left.size - 1)
else
traverse(root.left, random)
Following is an implementation in java:
public static void printRandom(TreeNode n, int randomNum) {
int leftSize = n.left == null ? 0 : n.left.size;
if (randomNum == leftSize + 1)
System.out.println(n.data);
else if (randomNum > leftSize + 1)
printRandom(n.right, randomNum - (leftSize + 1));
else
printRandom(n.left, randomNum);
}
Use size!
Pick a random number q between 0 and n.
Start from the root. If left->size == q return current node value. If the left->size < q the go right else you go left. If you go right subtract q -= left->size + 1. Repeat until you output a node.
This give you o(height of tree). If the tree is balanced you get O(LogN).
If the tree is not balanced but you still want to keep O(logN) you can do the same thing but cap the maximum number of iterations. Note that in this case not all nodes have the same probability of being returned.
Yes, use size!
As Sorin said, pick a random number i between 0 and n - 1 (not n)
Then perform the following instruction:
Treenode rand_node = select(root, i);
Where select could be as follows:
TreeNode select_rec(TreeNode r, int i) noexcept
{
if (i == r.left.size)
return r;
if (i < r.left.size)
return select_rec(r.left, i);
return select_rec(r.right, i - r.left.size - 1);
}
Now a very important trick: the null node must be a sentinel node with size set to 0, what has sense because the empty tree has zero nodes. You can avoid the use of sentinel, but then the select() operation is lightly more complex.
If the trees is balanced, then select() is O(log n)

Non recursive floor method for Binary search tree

I have been trying to get this to work but while it works for majority of the input sometimes it gives the wrong output. I have spent some time debugging the code and it seems the problem is when i get a Node that is smaller than the root but bigger than the left node under the root.
How can I traverse the right sub-tree and still return the right key if no node in the right sub-tree is the floor node for that key?
Recall that if you do anything recursively, it can be transformed* into iteration.
Let's consider taking the floor of a well-formed BST, which should simply be the smallest element which is less than or equal to your key in the tree. All we have to do is traverse the tree to get it.
Let's implement it recursively so we can tease out a few important corollaries between iteration and recursion.
// Assuming non-null root node with method declaration
private Node floor(Node root, Key key, Node lowestNode) {
if(key.compareTo(root.getKey()) <= 0) {
if(root.getLeft() != null) {
return floor(root.getLeft(), key, lowestNode);
} else {
return root.compareTo(lowestNode) < 0 ? root : lowestNode;
}
} else {
if(root.getRight() != null) {
lowestRightNode.add(root);
return floor(root.getRight(), key, lowestNode);
} else {
return lowestNode;
}
}
Let's walk through the conditions for success.
If we compare a node to be less than or equal to our key value:
If we have a left child, there's something smaller. Traverse down the left half of the tree.
Otherwise, we're at the floor - which means we're at the node whose value is less than or equal to our key. Return it.
Otherwise (our node has a value greater than our key):
If we have a right child, there's a chance that our work isn't done yet (something's smaller). We'd like to keep it around since we could step off of the tree, so let's store it, then traverse down the right half of the tree.
Otherwise, we've fallen off of the tree. Return the smallest element we've kept track of.
An example may look something like this:
9
/ \
3 14
/ \
1 2
With a key of 12:
Compare with 9. We're larger. Store 9 in our lowest node variable, recurse right.
Compare with 14. We're smaller, but we don't have a left child. We compare the value 14 to 9 and 9 is smaller, so we return the node with 9.
If we want to convert this into iteration, then think about your starting point, your conditional check, and your incrementation steps.
Starting point: A non-null node
Conditional check:
key.compareTo(root.getKey()) <= 0
root.getLeft() != null
continue
root.compareTo(lowestRightNode) < 0 ? root : lowestRightNode
terminal
else
root.getRight() != null
store temp value and continue
return lowestRightNode
terminal
Pay close attention to your continuation conditions, and what other work you'd have to do to keep track of the lowest node you've seen so far (only for the right-hand side, that is).
*: Some recursive operations are more painful to convert than others, of course.

Depth of a Node in BST including duplicates

i have implemented a function to find the depth of a node in a binary search tree but my implementation does not take care of duplicates. I have my code below and would like some suggestions on how to consider duplicates case in this function. WOuld really appreciate your help.
public int depth(Node n) {
int result=0;
if(n == null || n == getRoot())
return 0;
return (result = depth(getRoot(), n, result));
}
public int depth(Node temp, Node n, int result) {
int cmp = n.getData().compareTo(temp.getData());
if(cmp == 0) {
int x = result;
return x;
}
else if(cmp < 0) {
return depth(temp.getLeftChild(), n, ++result);
}
else {
return depth(temp.getRightChild(), n, ++result);
}
}
In the code you show, there is no way to prefer one node with same value over another. You need to have some criteria for differentiation.
You can retrieve the list of all duplicate nodes depths using the following approach, for example:
Find the depth of your node.
Find depth of the same node for the left subtree emerging from the found node - stop if not found.
Add depth of the previously found node (in 1) to the depth of the duplicate
Find depth of the same node for the right subtree emerging from the found node (in 1) - stop if not found.
Add depth of the previously found node (in 1) to the depth of the duplicate
Repeat for left and right subtrees.
Also see here: What's the case for duplications in BST?
Well, if there's duplicates, then the depth of a node with a given value doesn't make any sense on its own, because there may be multiple nodes with that value, hence multiple depths.
You have to decide what it means, which could be (not necessarily an exhaustive list):
the depth of the deepest node with that value.
the depth of the shallowest node with that value.
the depth of the first node found with that value.
the average depth of all nodes with that value.
the range (min/max) of depths of all nodes with that value.
a list of depths of all nodes with that value.
an error code indicating your query made little sense.
Any of those could make sense in specific circumstances.
Of course, if n is an actual pointer to a node, you shouldn't be comparing values of nodes at all, you should be comparing pointers. That way, you will only ever find one match and the depth of it makes sense.
Something like the following pseudo-code should do:
def getDepth (Node needle, Node haystack, int value):
// Gone beyond leaf, it's not in tree
if haystack == NULL: return -1
// Pointers equal, you've found it.
if needle == haystack: return value
// Data not equal search either left or right subtree.
if needle.data < haystack.data:
return getDepth (needle, haystack.left, value + 1)
if needle.data > haystack.data:
return getDepth (needle, haystack.right, value + 1)
// Data equal, need to search BOTH subtrees.
tryDepth = getDepth (needle, haystack.left, value + 1)
if trydepth == -1:
tryDepth = getDepth (needle, haystack.right, value + 1)
return trydepth
The reason why you have to search both subtrees when the values are equal is because the desired node may be in either subtree. Where the values are unequal, you know which subtree it's in. So, for the case where they're equal, you check one subtree and, if not found, you check the other.

Java: LinkedList reversal in chunks

If you are provided the head of a linked list, and are asked to reverse every k sequence of nodes, how might this be done in Java? e.g., a->b->c->d->e->f->g->h with k = 3 would be c->b->a->f->e->d->h->g->f
Any general help or even pseudocode would be greatly appreciated! Thanks!
If k is expected to be reasonably small, I would just go for the simplest thing: ignore the fact that it's a linked list at all, and treat each subsequence as just an array-type thing of things to be reversed.
So, if your linked list's node class is a Node<T>, create a Node<?>[] of size k. For each segment, load k Nodes into the array list, then just reverse their elements with a simple for loop. In pseudocode:
// reverse the elements within the k nodes
for i from 0 to k/2:
nodeI = segment[i]
nodeE = segment[segment.length-i-1]
tmp = nodeI.elem
nodeI.elem = nodeE.elem
nodeE.elem = tmp
Pros: very simple, O(N) performance, takes advantage of an easily recognizable reversing algorithm.
Cons: requires a k-sized array (just once, since you can reuse it per segment)
Also note that this means that each Node doesn't move in the list, only the objects the Node holds. This means that each Node will end up holding a different item than it held before. This could be fine or not, depending on your needs.
This is pretty high-level, but I think it'll give some guidance.
I'd have a helper method like void swap3(Node first, Node last) that take three elements at an arbitrary position of the list and reverses them. This shouldn't be hard, and could could be done recursively (swap the outer elements, recurse on the inner elements until the size of the list is 0 or 1). Now that I think of it, you could generalize this into swapK() easily if you're using recursion.
Once that is done, then you can just walk along your linked list and call swapK() every k nodes. If the size of the list isn't divisble by k, you could either just not swap that last bit, or reverse the last length%k nodes using your swapping technique.
TIME O(n); SPACE O(1)
A usual requirement of list reversal is that you do it in O(n) time and O(1) space. This eliminates recursion or stack or temporary array (what if K==n?), etc.
Hence the challenge here is to modify an in-place reversal algorithm to account for the K factor. Instead of K I use dist for distance.
Here is a simple in-place reversal algorithm: Use three pointers to walk the list in place: b to point to the head of the new list; c to point to the moving head of the unprocessed list; a to facilitate swapping between b and c.
A->B->C->D->E->F->G->H->I->J->L //original
A<-B<-C<-D E->F->G->H->I->J->L //during processing
^ ^
| |
b c
`a` is the variable that allow us to move `b` and `c` without losing either of
the lists.
Node simpleReverse(Node n){//n is head
if(null == n || null == n.next)
return n;
Node a=n, b=a.next, c=b.next;
a.next=null; b.next=a;
while(null != c){
a=c;
c=c.next;
a.next=b;
b=a;
}
return b;
}
To convert the simpleReverse algorithm to a chunkReverse algorithm, do following:
1] After reversing the first chunk, set head to b; head is the permanent head of the resulting list.
2] for all the other chunks, set tail.next to b; recall that b is the head of the chunk just processed.
some other details:
3] If the list has one or fewer nodes or the dist is 1 or less, then return the list without processing.
4] use a counter cnt to track when dist consecutive nodes have been reversed.
5] use variable tail to track the tail of the chunk just processed and tmp to track the tail of the chunk being processed.
6] notice that before a chunk is processed, it's head, which is bound to become its tail, is the first node you encounter: so, set it to tmp, which is a temporary tail.
public Node reverse(Node n, int dist) {
if(dist<=1 || null == n || null == n.right)
return n;
Node tail=n, head=null, tmp=null;
while(true) {
Node a=n, b=a.right; n=b.right;
a.right=null; b.right=a;
int cnt=2;
while(null != n && cnt < dist) {
a=n; n=n.right; a.right=b; b=a;
cnt++;
}
if(null == head) head = b;
else {
tail.right=b;tail=tmp;
}
tmp=n;
if(null == n) return head;
if(null == n.right) {
tail.right=n;
return head;
}
}//true
}
E.g. by Common Lisp
(defun rev-k (k sq)
(if (<= (length sq) k)
(reverse sq)
(concatenate 'list (reverse (subseq sq 0 k)) (rev-k k (subseq sq k)))))
other way
E.g. by F# use Stack
open System.Collections.Generic
let rev_k k (list:'T list) =
seq {
let stack = new Stack<'T>()
for x in list do
stack.Push(x)
if stack.Count = k then
while stack.Count > 0 do
yield stack.Pop()
while stack.Count > 0 do
yield stack.Pop()
}
|> Seq.toList
Use a stack and recursively remove k items from the list, push them to the stack then pop them and add them in place. Not sure if it's the best solution, but stacks offer a proper way of inverting things. Notice that this also works if instead of a list you had a queue.
Simply dequeue k items, push them to the stack, pop them from the stack and enqueue them :)
This implementation uses ListIterator class:
LinkedList<T> list;
//Inside the method after the method's parameters check
ListIterator<T> it = (ListIterator<T>) list.iterator();
ListIterator<T> reverseIt = (ListIterator<T>) list.listIterator(k);
for(int i = 0; i< (int) k/2; i++ )
{
T element = it.next();
it.set(reverseIt.previous());
reverseIt.set(element);
}

Categories