I'm trying to construct a binary tree (unbalanced), given its traversals. I'm currently doing preorder + inorder but when I figure this out postorder will be no issue at all.
I realize there are some question on the topic already but none of them seemed to answer my question. I've got a recursive method that takes the Preorder and the Inorder of a binary tree to reconstruct it, but is for some reason failing to link the root node with the subsequent children.
Note: I don't want a solution. I've been trying to figure this out for a few hours now and even jotted down the recursion on paper and everything seems fine... so I must be missing something subtle. Here's the code:
public static <T> BinaryNode<T> prePlusIn( T[] pre, T[] in)
{
if(pre.length != in.length)
throw new IllegalArgumentException();
BinaryNode<T> base = new BinaryNode();
base.element = pre[0]; // * Get root from the preorder traversal.
int indexOfRoot = -1 ;
if(pre.length == 0 && in.length == 0)
return null;
if(pre.length == 1 && in.length == 1 && pre[0].equals(in[0]))
return base; // * If both arrays are of size 1, element is a leaf.
for(int i = 0; i < in.length -1; i++){
if(in[i].equals(pre[0])){ // * Get the index of the root
indexOfRoot = i; // in the inorder traversal.
break;
}
} // * If we cannot, the tree cannot be constructed as the traversals differ.
if (indexOfRoot == -1) throw new IllegalArgumentException();
// * Now, we recursively set the left and right subtrees of
// the above "base" root node to whatever the new preorder
// and inorder traversals end up constructing.
T[] preleft = Arrays.copyOfRange(pre, 1, indexOfRoot + 1);
T[] preright = Arrays.copyOfRange(pre, indexOfRoot + 1, pre.length);
T[] inleft = Arrays.copyOfRange(in, 0, indexOfRoot);
T[] inright = Arrays.copyOfRange(in, indexOfRoot + 1, in.length);
base.left = prePlusIn( preleft, inleft); // * Construct left subtree.
base.right = prePlusIn( preright, inright); // * Construc right subtree.
return base; // * Return fully constructed tree
}
Basically, I construct additional arrays that house the pre- and inorder traversals of the left and right subtree (this seems terribly inefficient but I could not think of a better way with no helpers methods).
Any ideas would be quite appreciated.
Side note: While debugging it seems that the root note never receives the connections to the additional nodes (they remain null). From what I can see though, that should not happen...
EDIT: To clarify, the method is throwing the IllegalArgumentException # line 21 (else branch of the for loop, which should only be thrown if the traversals contain different elements.
EDIT2: Figured this out thanks to a helpful post from #Philip (coincidentally, we have the same first name... fun!). However, if anyone happens to have any advice on improving efficiency, I would appreciate the input.
this code is very suspicious to me
for(int i = 0; i < in.length -1; i++){
if(in[i].equals(base.element)){ // * Get the index of the root
indexOfRoot = i; // in the inorder traversal.
break;
} // * If we cannot, the tree cannot be constructed as the traversals differ.
else throw new IllegalArgumentException();
}
You enter the loop and i is set to 0, if i is less than in.length - 1 you evaluate the body of the loop which is an if expresion. At this point one of two things will happen
in[i] equals base.element in which case indexOfRoot will be set to 0 and you will break out of the loop
You throw an exception
Either way you never actually increment i
Try to rework this loop to do what you want, since it definitely isn't doing what you want now. You might try something like
int indexOfRoot = -1; //an impossible value
for(int i = 0; i < in.length -1; i++){
if(in[i].equals(base.element)){ // * Get the index of the root
indexOfRoot = i; // in the inorder traversal.
break;
}
}
if(indexOfRoot == -1){//if the root was never set
throw new IllegalArgumentException();
}
although that is still kinda ugly (for one thing, base.element never changes, so you might want to use pre[0] for clarity). And, by no means am I sure it is fully correct. Still, it is probably closer to what you want
Related
I'm practicing Java by working through algorithms on leetcode. I just solved the "Construct a binary tree from inorder and postorder traversal" problem and was playing with my code to try to get better performance (as measured by the leetcode compilation/testing). Here is the code I wrote:
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder.length == 1){
TreeNode root = new TreeNode(inorder[0]);
return root;
}
if(inorder.length == 0)
return null;
//int j = inorder.length; //Calculate this once, instead of each time the for loop executes
return reBuild(inorder, postorder, 0, inorder.length - 1, 0, postorder.length - 1);
}
public TreeNode reBuild(int[] inorder, int[] postorder, int inStart, int inEnd, int postStart, int postEnd){ //j passed in as argument here
if(inStart > inEnd)
return null; //base case
int rIndex = 0;
int j = inorder.length;
TreeNode root = new TreeNode(postorder[postEnd]); //Root is the last item in the postorder array
if(inStart == inEnd)
return root; //This node has no children
//for(int i = 0; i < inorder.length; ++i)
for(int i = 0; i < j; ++i){ //Find the next root value in inorder and get index
if(inorder[i] == root.val){
rIndex = i;
break;
}
}
root.left = reBuild(inorder, postorder, inStart, rIndex - 1, postStart, postStart - inStart + rIndex - 1); //Build left subtree
root.right = reBuild(inorder, postorder, rIndex + 1, inEnd, postEnd - inEnd + rIndex, postEnd - 1); //Build right subtree
return root;
}
}
My question concerns the for loop in the reBuild function. My first submission calculated the length of inorder each time the loop ran, which is obviously inefficient. I then took this out, and stored the length in a variable j, and used that in the for loop instead. This gave me a boost of ~1ms runtime. So far, so good. Then, I tried moving the calculation of j to the buildTree function, rationalizing that I don't need to calculate it in each recursive call since it doesn't change. When I moved it there and passed it in as a parameter, my runtime went back up 1ms, but my memory usage decreased significantly. Is this a quirk of how leetcode measures efficiency? If not, why would that move increase runtime?
If by calculating the length you mean accessing inorder.length then this is likely why you are losing performance.
When created, arrays hold onto a fixed value for their length called "length". this is a value not a method(thus no real performance used).
If j is never changed (ie j always equals inorder.length) The compiler likely ignores "j = inorder.length;" and simply accesses inorder.length when it sees j. you are then adding complexity to the function call by passing j where inorder (and thus inorder.length) is also present. Though this depends on the compiler implementation and may not actually happen.
In terms of access time, I think public object variables are slower than in-scope variables (think access inorder then access length).
warning hardware talk:
Another thing to consider is registers. These are data storage locations on the CPU itself which the code is actually run from (think HDD/SSD>RAM>cache>registers) and generally cant hold much more than 100 values at a time. Thus depending on the size of the current method (number of variables in scope) the code can run much faster or slower. Java seems to add a lot of overhead to this so for small functions, 1 or 2 extra values in scope can drastically affect the speed (as the program has to access cache).
I have an ArrayList, which contains game objects sorted by their 'Z' (float) position from lower to higher. I'm not sure if ArrayList is the best choice for it but I have come up with such a solution to find an index of insertion in a complexity faster than linear (worst case):
GameObject go = new GameObject();
int index = 0;
int start = 0, end = displayList.size(); // displayList is the ArrayList
while(end - start > 0)
{
index = (start + end) / 2;
if(go.depthZ >= displayList.get(index).depthZ)
start = index + 1;
else if(go.depthZ < displayList.get(index).depthZ)
end = index - 1;
}
while(index > 0 && go.depthZ < displayList.get(index).depthZ)
index--;
while(index < displayList.size() && go.depthZ >= displayList.get(index).depthZ)
index++;
The catch is that the element has to be inserted in a specific place in the chain of elements with equal value of depthZ - at the end of this chain. That's why I need 2 additional while loops after the binary search which I assume aren't too expensive becouse binary search gives me some approximation of this place.
Still I'm wondering if there's some better solution or some known algorithms for such problem which I haven't heard of? Maybe using different data structure than ArrayList? At the moment I ignore the worst case insertion O(n) (inserting at the begining or middle) becouse using a normal List I wouldn't be able to find an index to insert using method above.
You should try to use balanced search tree (red-black tree for example) instead of array. First you can try to use TreeMap witch uses a red-black tree inside to see if it's satisfy your requirements. Possible implementation:
Map<Float, List<Object>> map = new TreeMap<Float, List<Object>>(){
#Override
public List<Object> get(Object key) {
List<Object> list = super.get(key);
if (list == null) {
list = new ArrayList<Object>();
put((Float) key, list);
}
return list;
}
};
Example of usage:
map.get(0.5f).add("hello");
map.get(0.5f).add("world");
map.get(0.6f).add("!");
System.out.println(map);
One way to do it would to do a halving search, where the first search is half way thru your list (list.size()/2), then for the next one you can do half of that, and so on. With this exponential method, instead of having to do 4096 searches when you have 4096 objects, you only need 12 searches
sorry for the complete disregard for technical terms, I am not the best at terms :P
Unless I overlook something, your approach is essentially correct (but there's an error, see below), in the sense that your first while tries to compute the insert-index such that it will be placed after all lower OR EQUAL Z: there's correctly an equal sign in your first test (updating "start" if it yields TRUE).
Then, of course, there's no need to worry anymore about its position among equals. However, your follow-up while destroys this nice situation: the test in the first follow-up while yields always TRUE (one time) and so you move back; and then you need the second follow-up while to undo that. So, you should remove BOTH follow-up whiles and you're done...
However, there's a little problem with your first while, such that it doesn't always exactly do what the purpose is. I guess that the faulty outcomes triggered you to implement the follow-up whiles to "repair" that.
Here's the issue in your while. Suppose you have a try-index (start+end)/2 that points to a larger Z, but the one just before it has value Z. You then get into your second test (elseif) and set "end" to the position where that Z-value resides. Finally you wind up with precisely that position.
The remedy is simple: in your elseif assignment, put "end = index" (without the -1). Final remark: the test in the elseif is unnecessary, just else is sufficient.
So, all in all you get
GameObject go = new GameObject();
int index = 0;
int start = 0, end = displayList.size(); // displayList is the ArrayList
while(end - start > 0)
{
index = (start + end) / 2;
if(go.depthZ >= displayList.get(index).depthZ)
start = index + 1;
else
end = index;
}
(I hope I haven't overlooked something trivial...)
Add 1 to the least significant byte of the key (with carry); binary search for that insert position; and insert it there.
Your binary search has to be so constructed as to end at the leftmost of a sequence of duplicates, but this is trivial given an understanding of the various Binary search algorithms.
I have a Stack variable (java collection) which holds five integers and I was also given one int variable. Is it possible to sort the numbers in the given stack. I am not able to solve that. Please post here if you have ideas.
Stack<Integer> s = new Stack<Integer>();
s.push(5);s.push(3);s.push(4);s.push(1);s.push(1);
int a;
We should not create any new variable except the one given in the above code snippet and also should not use Collections.sort(s).
Terribly inefficient, but respects the rules :)
Stack<Integer> s=new Stack<Integer>();
s.push(5);s.push(3);s.push(4);s.push(1);s.push(1);
int a = -1;
while (a == -1) { // Here 'a' is used as a kind of boolean that tells us whether we need to keep checking for items to reorder or not.
for (a = 0; a < s.size() - 1; a++) { // Now 'a' becomes stack element's index.
if (s.get(a) > s.get(a + 1)) {
a = s.remove(a); // Here 'a' again changes meaning and holds the value that needs to be reordered.
s.push(a);
a = -1; // And here, 'a' is back to being used as a kind of boolean flag to control the outer loop.
break;
}
}
}
EDIT:
Basically, I take advantage of the fact that I know that Stack extends Vector. So I don't actually have to use only the standard Pop and Push methods to access/remove elements. I can use normal List methods.
And then, I just squeeze the most use I can from a by using it for different purposes at different times (exit flag, loop index, temp storage for value to reorder). Normally a very bad programming practice.
So the algorithm is basically that I loop through the Stack elements. Any time I find an element that is greater than the next, then I remove it, and then place it at the end of the Stack. At that moment, I stop the loop, and reset a to -1 to make sure I start the loop again. I keep doing this until I am able to loop through all the stack items without needing to reorder anything.
EDIT 2:
Here is another alternative that is a bit more complicated to read, but still respects the rules, and performs better following the bubble sort pattern. The principles used are pretty much the same as my first attempt (abusing the Stack as a List + using variable a for multiple uses).
Stack<Integer> s=new Stack<Integer>();
s.push(5);s.push(3);s.push(4);s.push(1);s.push(1);
int a = -1;
while (a < 0) { // keep looping if the previous loop performed at least one swap.
a = 0;
// if 'a' is >= 0, then it simply holds the index.
// if 'a' < 0, then the index can be obtained by applying the bitwise complement operator.
while ((a < 0 ? ~a : a) < (s.size() - 1)) { // loop all items except the last one.
if (s.get(a < 0 ? ~a : a) > s.get((a < 0 ? ~a : a) + 1)) { // if this item is greater than the next, a swap is needed.
s.insertElementAt(s.remove(a < 0 ? ~a : a), (a < 0 ? ~a : a) + 1); // swap this value with the next.
// If this was not done already, flag the fact that a swap was performed by
// applying the bitwise complement operator to 'a'.
// This serves as a flag to let the outer loop know
// that we'll need to perform the stack loop again.
if (a >= 0) {
a = ~a;
}
}
// increment index. Or if the bitwise complement operator was applied,
// then go the opposite way since the value is now negative.
if (a >= 0) {
a++;
} else {
a--;
}
}
}
EDIT 3: Revised my last algorithm to use the bitwise complement operator rather than Math.abs().
Also, I would like to point out that, unlike some other clever attempts, this algorithm doesn't really have any limitations. It won't potentially suffer from a StackOverflowException because of too many recursive calls, because no recursion is used. Memory used is stable. And you can have any int value in the Stack, even negative ones, and it will work fine.
It's possible to do, but you're going to be cheating a little bit - you're going to use a second stack to do it.
I don't mean that you're explicitly declaring another stack; you're going to be recursing through this method.
Bear in mind that this approach has some limitations; it can handle sequential data just fine (that is, it can reverse a stack just fine), but dealing with more jumbled data is a lot trickier as we can only see up to two elements in the future (peek and holder).
This also inverts the approach and doesn't order them in a way you'd prescribe (1 to 5), but figuring out the correct condition from the code should be a trivial matter.
The approach is:
Handle null and empty stacks by returning what was given to us
Handle a stack of size 1 by returning what was given to us
In the process, we pop the stack and store that in the holder variable.
If what's in the stack next is less than the holder variable, we act:
Pop the stack again, multiply it by 10, and add this to the holder. We do the multiplication here so that we can (roughly) store two ints at once.
Push the remainder value (holder % 10) into the stack.
Recurse, repeating the instructions.
Once recursion has exhausted, we push the value we multiplied by 10 back onto the array by dividing the holder by 10.
Otherwise, we put back what we had found and return the stack.
public Stack<Integer> sortStack(Stack<Integer> stack) {
// no-op on empty stacks
if(null == stack || stack.empty()) {
return stack;
}
// pop stack and place in holder
while(true) {
int holder = stack.pop();
// no-op on stacks of size 1
try {
stack.peek();
} catch(EmptyStackException e) {
// Stack only had one element; put it back and return the stack
stack.push(holder);
return stack;
}
if(stack.peek() < holder) {
holder += stack.pop() * 10;
stack.push(holder % 10);
stack = sortStack(stack);
stack.push(holder / 10);
} else {
//put it back
stack.push(holder);
break;
}
}
return stack;
}
Since Stack implements List and Integer implements Comparable just:
Collections.sort(s);
You can use bubble sort to do it, as the following:
Stack<Integer> s = new Stack();
s.push(5);
s.push(3);
s.push(4);
s.push(1);
s.push(1);
int a = 0;
while (a != s.size() - 1) {
if (a != s.size() - 1) {
if (s.elementAt(a) >= s.elementAt(a + 1)) {
a++;
} else {
s.push(s.remove(a));
a = 0;
}
}
}
System.out.println(s.toString());
Here i found the perfect answer from geeksforgeeks which uses recursion.
http://www.geeksforgeeks.org/sort-a-stack-using-recursion/
Just posting the same algorithm here.
Algorithm:
We can use below algorithm to sort stack elements:
sortStack(stack S)
if stack is not empty:
temp = pop(S);
sortStack(S);
sortedInsert(S, temp);
Below algorithm is to insert element is sorted order:
sortedInsert(Stack S, element)
if stack is empty OR element > top element
push(S, elem)
else
temp = pop(S)
sortedInsert(S, element)
push(S, temp)
So I wrote a Graph class and I can't seem to do a depth first search on it properly depending on the sequencing of nodes. Here's what I mean:
If my graph looks like this:
A-B-D
|/
C
The DFS returns: "ABC"
But when it looks like this:
A-B
| |
D C
|
E
It will print ABCDE correctly.
The problem I've found lies in my getUnvisitedAdjacentNode() function. Here is the function:
public int getUnvisitedAdjacentNode(int n) {
for (int i = 0; i < this.nodeList.size(); i++) {
if (this.edges[n][i] == 1 && this.nodeList.get(i).wasVisited == false) {
return i;
}
}
return -1;
}
The problem, I've found is because it goes in "order" (just a for loop) , it will never get traverse D in the first situation because B gets visited and after C gets visited, B simply get's popped off of the stack. Maybe this isn't the problem.
Here's the code for my actual DFS traversal.
public void depthFirstTraverse() {
Stack<Node> stack = new Stack<Node>();
nodeList.get(0).wasVisited = true;
System.out.println(nodeList.get(0).item);
stack.push(nodeList.get(0));
while (!stack.isEmpty()) {
int nextNode = this.getUnvisitedAdjacentNode(stack.peek().index);
if (nextNode == -1) {
stack.pop();
} else {
nodeList.get(nextNode).wasVisited = true;
System.out.println(nodeList.get(nextNode).item);
stack.push(nodeList.get(nextNode));
}
}
for (int i = 0; i < nodeList.size(); i++) {
nodeList.get(i).wasVisited = false;
}
}
Fortunately I found my own mistake, the code above is all correct, except it was in the code that I hadn't pasted.
In case anybody cares, the problem lied in the fact that I completely disregarded the fact that ArrayLists have an "IndexOf()" method (stupid, I know) and decided to hack my own "index" field into my Node class. When dealing with my own indices, I had a minor bug which screwed up the traversal.
So the old line in my DFS algorithm looks like this:
int nextNode = this.getUnvisitedAdjacentNode(stack.peek().index);
But it should be:
int nextNode = this.getUnvisitedAdjacentNode(this.nodeList.indexOf(stack.peek()));
You said it. If you pop a node off of the stack, you need to make sure that all of its unvisited neighbors are on the stack first. Otherwise, there's no guarantee that everyone will be visited.
For example, in the first diagram you gave, if node A is visited first, and then node B, either node C or D will be visited next. However, if you only push one of them onto the stack, and then remove B, there will be no way of reaching the last one.
So what you may want to do it write a function getAllUnvisitedAdjacentNodes and push all of them onto the stack before you pop.
I have a n-ary tree which contains key values (integers) in each node. I would like to calculate the minimum depth of the tree. Here is what I have come up with so far:
int min = 0;
private int getMinDepth(Node node, int counter, int temp){
if(node == null){
//if it is the first branch record min
//otherwise compare min to this value
//and record the minimum value
if(counter == 0){
temp = min;
}else{
temp = Math.min(temp, min);
min = 0;
}
counter++;//counter should increment by 1 when at end of branch
return temp;
}
min++;
getMinDepth(node.q1, counter, min);
getMinDepth(node.q2, counter, min);
getMinDepth(node.q3, counter, min);
getMinDepth(node.q4, counter, min);
return temp;
}
The code is called like so:
int minDepth = getMinDepth(root, 0, 0);
The idea is that if the tree is traversing down the first branch (branch number is tracked by counter), then we set the temp holder to store this branch depth. From then on, compare the next branch length and if it smaller, then make temp = that length. For some reason counter is not incrementing at all and always staying at zero. Anyone know what I am doing wrong?
I think you're better off doing a breadth-first search. Your current implementation tries to be depth-first, which means it could end up exploring the whole tree if the branches happen to be in an awkward order.
To do a breadth-first search, you need a queue (a ArrayDeque is probably the right choice). You'll then need a little class that holds a node and a depth. The algorithm goes a little something like this:
Queue<NodeWithDepth> q = new ArrayDeque<NodeWithDepth>();
q.add(new NodeWithDepth(root, 1));
while (true) {
NodeWithDepth nwd = q.remove();
if (hasNoChildren(nwd.node())) return nwd.depth();
if (nwd.node().q1 != null) q.add(new NodeWithDepth(nwd.node().q1, nwd.depth() + 1));
if (nwd.node().q2 != null) q.add(new NodeWithDepth(nwd.node().q2, nwd.depth() + 1));
if (nwd.node().q3 != null) q.add(new NodeWithDepth(nwd.node().q3, nwd.depth() + 1));
if (nwd.node().q4 != null) q.add(new NodeWithDepth(nwd.node().q4, nwd.depth() + 1));
}
This looks like it uses more memory than a depth-first search, but when you consider that stack frames consume memory, and that this will explore less of the tree than a depth-first search, you'll see that's not the case. Probably.
Anyway, see how you get on with it.
You are passing the counter variable by value, not by reference. Thus, any changes made to it are local to the current stack frame and are lost as soon as the function returns and that frame is popped of the stack. Java doesn't support passing primitives (or anything really) by reference, so you'd either have to pass it as a single element array or wrap it in an object to get the behavior you're looking for.
Here's a simpler (untested) version that avoids the need to pass a variable by reference:
private int getMinDepth(QuadTreeNode node){
if(node == null)
return 0;
return 1 + Math.min(
Math.min(getMinDepth(node.q1), getMinDepth(node.q2)),
Math.min(getMinDepth(node.q3), getMinDepth(node.q4)));
}
Both your version and the one above are inefficient because they search the entire tree, when really you only need to search down to the shallowest depth. To do it efficiently, use a queue to do a breadth-first search like Tom recommended. Note however, that the trade-off required to get this extra speed is the extra memory used by the queue.
Edit:
I decided to go ahead and write a breadth first search version that doesn't assume you have a class that keeps track of the nodes' depths (like Tom's NodeWithDepth). Once again, I haven't tested it or even compiled it... But I think it should be enough to get you going even if it doesn't work right out of the box. This version should perform faster on large, complex trees, but also uses more memory to store the queue.
private int getMinDepth(QuadTreeNode node){
// Handle the empty tree case
if(node == null)
return 0;
// Perform a breadth first search for the shallowest null child
// while keeping track of how deep into the tree we are.
LinkedList<QuadTreeNode> queue = new LinkedList<QuadTreeNode>();
queue.addLast(node);
int currentCountTilNextDepth = 1;
int nextCountTilNextDepth = 0;
int depth = 1;
while(!queue.isEmpty()){
// Check if we're transitioning to the next depth
if(currentCountTilNextDepth <= 0){
currentCountTilNextDepth = nextCountTilNextDepth;
nextCountTilNextDepth = 0;
depth++;
}
// If this node has a null child, we're done
QuadTreeNode node = queue.removeFirst();
if(node.q1 == null || node.q2 == null || node.q3 == null || node.q4 == null)
break;
// If it didn't have a null child, add all the children to the queue
queue.addLast(node.q1);
queue.addLast(node.q2);
queue.addLast(node.q3);
queue.addLast(node.q4);
// Housekeeping to keep track of when we need to increment our depth
nextCountTilNextDepth += 4;
currentCountTilNextDepth--;
}
// Return the depth of the shallowest node that had a null child
return depth;
}
Counter is always staying at zero because primitives in java are called by value. This means if you overwrite the value in a function call the caller won't see the change. Or if you're familiar with C++ notation it's foo(int x) instead of foo(int& x).
One solution would be to use an Integer object since objects are call-by-reference.
Since you're interested in the minimum depth a breadth first solution will work just fine, but you may get memory problems for large trees.
If you assume that the tree may become rather large an IDS solution would be the best. This way you'll get the time complexity of the breadth first variant with the space complexity of a depth first solution.
Here's a small example since IDS isn't as well known as its brethren (though much more useful for serious stuff!). I assume that every node has a list with children for simplicity (and since it's more general).
public static<T> int getMinDepth(Node<T> root) {
int depth = 0;
while (!getMinDepth(root, depth)) depth++;
return depth;
}
private static<T> boolean getMinDepth(Node<T> node, int depth) {
if (depth == 0)
return node.children.isEmpty();
for (Node<T> child : node.children)
if (getMinDepth(child, depth - 1)) return true;
return false;
}
For a short explanation see http://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search