How to find the depth of a tree iteratively in Java? - java

In an interview, I was asked to find the depth of the tree. I did it recursively, but then interviewer asked me to do it using iteration. I did my best, but i don't think he looked quite convinced. can anyone write the pseudo-code here or code would be preferable...Thanks for reading the post.

Check the answer provided at Way to go from recursion to iteration. Bottom line is that you don't have to solve the problem twice. If you have a perfectly good recursive algorithm, then transform it into an iteration.

Tree<Object> tree = ...; // source
class NodeMarker {
public NodeMarker(TreeNode node, int depth) { ... }
public TreeNode node;
public int depth;
}
int depth = 0;
List<NodeMarker> stack = new LinkedList<NodeMarker>();
for (TreeNode node : tree.getChildren())
stack.add(new NodeMarker(node, 1);
while (stack.size() > 1) {
NodeMarker marker = stack.get(0);
if (depth < marker.depth)
depth = marker.depth;
if (marker.node.hasChildren())
for (TreeNode node : marker.node.getChildren())
stack.add(new NodeMarker(node, marker.depth + 1);
}

Iteration rather than recursion means that is you go down the tree, rather than having each function call spawn two new function calls, you can store each member of the layer in an array. Try starting with a (one element) array containing a pointer to the root. Then, in a loop (I'd just use a while (1)) iterate over that array (currentLayer) and create a new array (nextLayer) and add the children of each element in currentLayer to nextLayer. If nextlayer is empty, you're now at the deepest layer, otherwise increment depth by one, copy nextLayer to currentLayer, and do it again.

Related

How can I fix my array so I don't have an IndexOutOfBoundsException?

For a HW assignment, I was tasked to add a bunch of methods into a BinarySearchTree class. Two methods I have are balance and InsertTree (I think it should've been named InsertNode). The authors from the textbook provided pseudo code of what the methods should look like. Both methods work with each other; balance is supposed to take an unbalanced tree and insert each element into an array. I believe InsertTree is supposed to take the elements from the array and put them back into the new formed tree.
The BST Class itself is quite large so I don't think posting it is a good idea. But you can find the Source code here under Sample Materials. The code in reference is in the ch07.trees package.
This is my interpretation of the authors pseudo code so far:
ArrayList<T> array = new ArrayList<T>();
public void balance()
// Will read, store, and recreate the tree
{
Iterator<T> iter = this.iterator();
int index = 0;
while(iter.hasNext())
{
array.add(iter.next());
index++;
}
System.out.println(array.toString());
System.out.println(index);
tree = new BinarySearchTree<T>();
tree.InsertTree(0, index -1);
}
public void InsertTree(int low, int high)
// Will find the mid-point and insert other elements into left and right subtrees
{
if (low == high)
{
tree.add(array.get(low));
}
else if((low + 1) == high)
{
tree.add(array.get(low));
tree.add(array.get(high));
}
else
{
int mid = (low + high)/2;
tree.add(array.get(mid));
tree.InsertTree(low,mid-1);
tree.InsertTree(mid+1,high);
}
}
I have to use ArrayList because all of the methods are generics of type T. In my driver class I am simply adding an unbalanced set of elements [A, B, C, D, E, F] and index will correctly show I have incremented index to 6. But, when the new tree calls for InsertTree( 0, index - 1), I get this:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at ch07.trees.BinarySearchTree.InsertTree(BinarySearchTree.java:180)
at ch07.trees.BinarySearchTree.balance(BinarySearchTree.java:163)
at ch07.trees.HWDriver.main(HWDriver.java:67)
Line 163 is tree.InsertTree(0, index -1); and Line 180 is tree.add(array.get(mid));
Seems the problem is involved with the mid-point, but I'm not sure what the issue could be. I'm not an expert at using ArrayLists, so any help on solving this would be much appreciated.
edit:
I believe the problem has been fixed. I put the array that I created back into the balance method instead of outside the method, and added the array to the InsertTree methods arguments. Then, I had to change every conditional output from this.tree.add to this.add. I also moved my BinarySearchTree tree back into the balanced method because before I was getting a NullPointerException.
Whether or not my method is working as intended is still to be determined.
Look what happens when you have an empty collection...
int index = 0;
[...]
tree = new BinarySearchTree<T>();
tree.InsertTree(0, index -1);
You are trying to insert something at index (-1). That is not legal.
Here is your answer more concisely:
this.tree = new BinarySearchTree<T>();
this.tree.InsertTree(0, index-1);
So you have created a new, empty tree and stored it in the member variable "tree". You then attempt tell your new, empty tree to insertTree(0, 5) .

Delete elements within a Linked List

Looking for help again as my professor seems to do an awful job of explaining things (assumes that we know way too much about java programming, when in fact, it's the first java class most of us are taking).
Not looking for someone to write the code for me, but rather someone who can let me know if I'm on the right track and guide me in the right direction. I really want to learn this stuff, not be spoon-fed it, but the professor is making it very hard to do so, so I turn here for help.
The question is to take a LinkedList and create a function to delete the k-th element in that list. I have figured out how to remove the first item if k == 0, but I'm getting lost on how to access the proper element for the "k" within my loop. Here's what I have so far:
public class MyLinked {
static class Node {
public Node(double item, Node next) {
this.item = item;
this.next = next;
}
public double item;
public Node next;
}
int N;
Node first;
// delete the kth element (where k is between 0 and N-1 inclusive)
public void delete(int k) {
if (k < 0 || k >= N) throw new IllegalArgumentException();
{
if (k == 0) {
remove(first.item);
} else if (k > 0) {
kElem = LinkedList.get();
remove(kElem);
}
}
}
}
I'm trying to assign a variable to the .get function but I am definitely wrong there, but not quite sure how to go about this. I know I need to get the value of the k-th element and delete it, however.
I'm also aware that after this, I need to adjust the pointers within the LinkedList to fill the gap where the element I deleted would have been.
Thank you.
Your Link List looks like this:
On this image prev is the object in front of the object you want to delete. Cur is the object you want to delete.
You loop until the next-pointer targets the object you want to delete. After that you set the next pointer of prev to the the object, which follows cur (cur is the object you want to delete).
In pseudo-code it would look like this:
prev = head;
while(prev.next != cur) {
prev = prev.next
}
After this step the prev is on the correct position.
You can see, that this algorithm works with every case except removing the head. You can make a check if you are removing the head and use a different algorithm or you use a dummy-node. Use the dummy-node as head and a dummy-node as tail (here not displayed, but used in double-linked-lists). This dummy-nodes are called sentinels. You won't ever remove this sentinel but your algorithm works without the additional-check because you will remove elements > 0.
Sources:
https://www.cs.cmu.edu/~adamchik/15-121/lectures/Linked%20Lists/linked%20lists.html
In the comments I saw a discussion about clean-code. If you are learning clean-code you will see, that a lot of algorithms are easier to understand, if the variables express their purpose. For example N should be size. But in a different context it could be an upper-limit-of-elements for a cache. There is a good book on this topic: Clean Architecture: A Craftsman's Guide to Software Structure and Design (Robert C. Martin Series)
What do you think is easier to read:
int[][] a = new int[100][200];
for(int i = 0; i < a.length) {
for(int j = 0; j < a[i].length) {
a[i][j] = i*j;
}
}
or this:
int[][] productOfRowColumns = new int[100][200];
for(int row = 0; i < productOfRowColumns.length) {
for(int column = 0; j < productOfRowColumns[row].length) {
productOfRowColumns[row][column] = row*column;
}
}
First go to the k-1 element. Set element.next=element.next.next. Thats how you skip the element, which should be deleted.
Exception: When k=0 (the head element), just set head=head.next.
Optionally you can set next = null for the deleted element (when you went for k-1 elements, deleted=element.next before setting element.next=element.next.next. then say deleted.next=null to clear its next-pointer.
There is also a second common way where you go to the kth element, but you always save the previous (k-1) element in a variable. Performance wise it is worse, because you update 2 variables in each step. It could be more intuitive. Check that video: https://www.youtube.com/watch?v=2RwWsHePdr8 (I hope yt-links are allowed on SO)
By the way, your
static class Node {
public Node(double item, Node next) {
this.item = item;
this.next = next;
}
public double item;
public Node next;
}
int N;
Node first;
is your implementation of the list. LinkedList is the implementation provided by java. https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html. You can not mix them.
Hints:
Don't forget to decrease the size of the list (N--;)
You can "go" to the n-th element with "Node current=head; for(int i = 0; i < n; i++) current=current.next;"
What I mean with "head" is your "first". It is the first element of the list.
The "get" method does not do what you want. You will need to write the code to iterate to position k-1 and switch the pointer, as you said:-
eg. list 1->2->3->4, k=2
iterate using next pointer upto 2, switch the next pointer to point to 4. You don't need to do anything else(remove etc)

Is it possible to print each level of a binary tree on a separate line using depth-first traversal?

I am familiar with the use of a queue to print each level in a separate line in O(n) time. I want to know if there is any way to do this using pre-order, in-order or post-order traversal. I have following code but I have no idea what to do with depth parameter. Only idea I have is using an array of linked lists to store all nodes while traversing the tree, consuming O(n) extra space. Is there any better way to do this?
class Node {
int key;
Node left;
Node right;
Node(int value) {
key = value;
left = null;
right = null;
}
}
public class bst {
private Node root;
bst() {
root = null;
}
private void printTreeRec(Node root, int depth) {
if(root != null) {
System.out.println(root.key);
printTreeRec(root.left, depth + 1);
printTreeRec(root.right, depth + 1);
}
}
void printTree() {
printTreeRec(root, 0);
}
public static void main(String[] Args) {
bst tree = new bst();
tree.insert(25);
tree.insert(15);
tree.insert(35);
tree.insert(7);
tree.insert(18);
tree.insert(33);
tree.insert(36);
tree.printTree();
}
}
It is not possible with the mentioned approaches indeed because they go depth-first that is they always go in a direction until they reach the end of the branch.
Or at least not with printing the output directly on the console, as the algorithm executes.
This is not a rigorous proof but it shall describe the issue:
Preorder
System.out.println(root.key);
printTreeRec(root.left, depth + 1);
printTreeRec(root.right, depth + 1);
At a particular node you print the current node first. Then, you go left, and you print that node, and so on. As you have already moved down the console, and you can't go back, this approach won't work
Inorder
printTreeRec(root.left, depth + 1);
System.out.println(root.key);
printTreeRec(root.right, depth + 1);
In this case you start at the root, and you go left. Still left, until there are no more children nodes. And then you print. But now you will go up the tree, and what will you do with the focus on the console line? Once again you have to move forward. Also not possible in this case.
Postorder
printTreeRec(root.left, depth + 1);
printTreeRec(root.right, depth + 1);
System.out.println(root.key);
In this case you start at the root, and you go left. Until you can. When you can't you start going right. Go right until you can. Then start printing. But now, similarly as above, you will go up the tree, and what will you do with the focus on the console line? Once again you have to move forward. Not possible again.
How can we make it work?
We should cheat, and pass a level variable to know the level at which we are at a particular moment. Fill a data structure, like map, that will contain node values per level, and after the algorithm is finished computing, print the result, one level per line, using the map.
You can reference the discussion at here: Java DFS solution. Post the code below for the convenience.
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
levelHelper(res, root, 0);
return res;
}
public void levelHelper(List<List<Integer>> res, TreeNode root, int height) {
if (root == null) return;
if (height >= res.size()) {
res.add(new LinkedList<Integer>());
}
res.get(height).add(root.val);
levelHelper(res, root.left, height+1);
levelHelper(res, root.right, height+1);
}

What kind of maze Solving Algorithm is this?

I am trying to figure out if this algorithm is A* (A-Star) Algorithm or whatever but still I am confused.
Stack<Cell> stack = new Stack<>();
stack.push(maze.start());
stack.peek().mark(SOLUTION_MARK);
while (!stack.peek().hasMark(Cell.END)) {
Cell current = stack.peek();
ArrayList<Cell> dirs = current.neighbors();
boolean found = false;
for (Cell next : dirs) {
if (next.hasMark(ERROR_MARK) || next.hasMark(SOLUTION_MARK)) {
continue;
}
stack.push(next);
next.mark(SOLUTION_MARK);
found = true;
break;
}
if (!found) {
stack.pop().mark(ERROR_MARK);
}
for (MazeBody listener : listeners) {
listener.repaint();
}
}
Mark.java
public final class Mark {
private static Map<String, Mark> TABLE = new HashMap<>();
private String name;
private Mark(String markName) {
name = markName;
}
public static Mark get(String name) {
Mark mark = TABLE.get(name);
if (mark == null) {
mark = new Mark(name);
TABLE.put(name, mark);
}
return mark;
}
}
This is Depth First Search written iteratively rather than recursively.
Recursive DFS (preorder) pseudocode looks like:
visit (current node)
for each child node of current node
if node is not explored
dfs (node)
Iterative version of DFS looks like:
Put current node on stack
In a while loop pop the stack if not empty
visit (popped node)
push all Unvisited and NotVisiting neighbors of popped node on the stack
End while
Unvisited and NotVisiting in the Iterative version means that the node is neither visited before, nor it is in the stack for visiting.
The time complexity of this algorithm depends on whether the graph has been stored as adjacency list or adjacency matrix. For list, it'd be O(n). For matrix, it'd become O(n2) because even though you explore every node only once, you have to visit every row and column of the matrix to know if there is a path between a node X and node Y.
The space complexity of this algorithm can go to worst of O(n), happening when the graph would have each node having only one neighbor, becoming like a singly linked list.
Based on what you show I would say it is depth-first search, but with a check whether the place has already been scheduled for visit. Since it uses a stack, it will always first visit the places deeper in the search tree. But from the moment it adds a place to the stack, it marks the place as a solution mark to prevent it from being re-evaluated if another path would reach the same place.
Note however that it will mark every tile a SOLUTION_MARK unless it cannot come up with nodes others than marked with a SOLUTION_MARK or an ERROR_MARK. It will thus mark more tiles than the tiles contributing to (shortest) the solution. In that sense it is not really a maze solving algorithm: it simply marks tiles as SOLUTION_MARK if there is at least another tile not yet scheduled that can contribute to a solution. The algorithm will finish if it has marked all reachable tiles.

Homework: Return the least element in the set greater than given element BST

So I've been stuck for hours trying to figure out this problem.
Given a randomly generated BST and using the method header:
public E higher(E elt)
Where elt is a randomly generated value within the tree's range, I need to find the least element in the set greater than elt.
Nodes contain left links and right links, but no parent link.
The tree in the linked image reads with the root being the leftmost node
BST.
So if elt is 27, then I want to return the node containing 28.
I need to run this in O(logn) time, and everything I've tried has not worked.
I'm not looking for someone to do my homework for me, but I have no clue what to do at this point.
I can provide more detail and source code if it's needed.
Edit: I'll put this here, though it's woefully inadequate. I feel as though this would be easier if I could do this recursively but I can't think of a way to do that.
Node n = root;
//need to get this into a loop somehow and break out when I've found
//the right value
int c = myCompare(elt, ((E) n.data));
if (c < 0) {
n = n.left;
//now I need to compare this against any children
} else if (c > 0) {
n = n.right;
//now I need to compare this against any children
}
return ((E)n.data);
This depends on the fundamental property of BSTs: the left child is less than the parent, the right child is greater than the parent. If you look at a sample BST you will quickly notice a few properties, and you can see why the following algorithm will work.
If the current node is less than the given value, move right, otherwise move left. If you reach a point where moving left will give you a value that is too low (or you hit a leaf) then you found the correct node. Or, in pythonic pseudo-code:
while (true):
if (node.value <= elt):
node = node.right
else:
if (node.left.value < elt):
return node.value
else:
node = node.left
The pseudo-code obviously needs to check for errors, if a node is a leaf, etc., but this general algorithm will give you the expected output in the desired time complexity (assuming a balanced BST).
One possible approach is to find the specified node and to get the next least node from there (if you're allowed to use helper methods).
If we say that the root node is 'n' and we know that the desired value is inside the BST, then you can traverse through it to find the node that contains the given value with something like this:
public Node search(Node n, E obj)
{
if(obj.compareTo(n.getValue()) > 0)
{
return search(n.getRight(), obj);
}
else if(obj.compareTo(n.getValue()) < 0)
{
return search(n.getLeft(), obj);
}
else
{
return n;
}
}
If the objective were to retrieve the least value from a binary search tree, a simple recursive method like this would work:
public Node getLeast(node n)
{
if(n.getLeft()==null)
{
return n;
}
return getLeast(n.getLeft());
}
Using the principles of a binary search tree, we know that the least value greater than a given node is just the least node after the right child of the given node. So, we can just use this method to obtain the desired value:
getLeast(search(n,elt).getRight());

Categories