Sorting numbers in Stack using one int variable - java

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)

Related

How to quickly insert an element into array with duplicates after all of the equal elements?

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.

Recursion and Recursive Methods

I'm studying for my computer science final and am going back over some of the things that I never quite grasped when we went over them in class. The main thing being recursion. I think I've got the hang of the simple recursion example but am trying to work through one that was on a previous exam and am having trouble figuring out how it should be done.
Here is the question:
Texas numbers (Tx(n)) are defined as follows for non-negative numbers (assume true):
Tx(n) = 10 if n is 0
Tx(n) = 5 if n is 1
Tx(n) = 2*(Tx(n-1) + Tx(n-2) if n >= 2
We are then to write the recursion function for Texas numbers, after making some corrections after the test, here's what I've come up with, I think it's right, but not 100% sure.
public int Tx(int n) {
if(n == 0)
return 10;
else if (n == 1)
return 5;
else
return 2*(Tx(n-1) + Tx(n-2));
}
Then we are asked to computer the value of Tx(5). This is where I'm stuck. If the return statement for the else was simply n-1, I think I'd be able to figure it out, but the n-1 + n-2 is completely throwing me off.
Can anyone explain how this would work, or share some links that have similar examples. I have tried looking this up online and in my textbook but the examples I've found are either so advanced that I have no clue what's going on, or they only deal with something like return n-1, which I already know how to do.
Let's start with Tx(2). n > 1, so we have 2*(Tx(n-1) + Tx(n-2)) which is 2*(Tx(1) + Tx(0)).
But we already know Tx(1) and Tx(0)! So just substitute them in and you get 2*(5 + 10) -> 30. Great, so now we know T(2).
What about T(3)? 2*(Tx(2) + Tx(1)). Nice, we already know these too :) Again, just fill them in to get 2*(30 + 5) -> 70.
You can work forwards to get to Tx(5).
Your code is logically correct, you should just be using == to test equality, a single = is for assignment.
When you run your method, it will work backwards and solve smaller and smaller subproblems until it gets to a point where the answer is known, these are your base cases.
Tx(3)
2* Tx(2) + Tx(1)
2*Tx(1) + Tx(0) (5)
(5) (10)
In order for recursion to work, whatever you are doing each time to break the problem down into smaller problems needs to make some progress towards the base case. If it doesn't, you will just infinitely recurse until your computer runs out of space to store all of the repeated calls to the same function.
public int Tx(int n) {
if(n == 0)
return 10;
else
return Tx(n+1); // n will never reach 0!
}
Tx(1) becomes Tx(2) -> Tx(3) -> Tx(4) -> Tx(5) etc.
Your implementation is good, only one minor mistake - in the conditions you should replace = with == - it's not an assignment - it's a comparison.
By the way, what would you expect your method to return for Tx(-1) ?
You have implemented it right just change = with ==.
If you want to further reduce the time complexity you can store the result in an array global to the function so that your function doesnot compute results again and again for a same number this will only save you some time for large computations.
You can use something like this.
public int tx(int n , int []arr) {
if (arr[n] == 0) {
if (n == 1) {
arr[n] = 10;
}
else if (n == 2) {
arr[n] = 5;
}
else {
arr[n] = 2 * (tx((n - 1), arr) + tx((n - 2), arr));
}
}
return arr[n];
}
See whenever you ask the computer for the value Tx(5) it will call the recursive function and so the program will execute the else part because value of n=5.
Now in the else part 2*(Tx(n-1)+Tx(n-2)) will be executed.
In first iteration it will become 2*((2*(Tx(3)+Tx(2)))+(2*(Tx(2)+Tx(1)))) . The iteration will be continued until the value of n become 0 or 1.

Understanding basic recursion function in Java to calculate positive integers in array

I am trying to learn recursion in Java and have an array that takes in continuous input until the Scanner reads in a 0.
From there I have a method that (attempts) to calculate the number of positive integers in the array using recursion. This is the first recursive function I have ever written and I keep getting a stackoverflow error.
I have read tutorials and I still can't wrap my head around the basic understanding of recursion.
public class reuncF {
private static int start = 0;
private static int end = 98;
public static void main(String[] args) {
input = input.nextDouble();
list[i] = numInput;
computeSumPositive(numList, count);
}
}
return positives += solve(numbers, count++);
}
}
You forgot to stop your recursion!
There has to be some case where computeSumPositive returns without calling itself again. Otherwise it'll just keep going forever, never getting back to you.
If you did it with a loop, the loop would look like this:
int positives = 0;
for (int i = 0; i < numList.length; ++i) {
if (numList[i] > 0) {
positives++;
}
}
To do that recursively, you just find out what are the variables used in the loop. They are i, numList and positives.
computeSumPositive(int i, double[] numList, int positives)
Then we take a look at what the loop does. First, it checks whether we went too far,
so our recursive function should do that too. It'll have to return instead of just falling through like the loop does. And obviously, it must return the result:
{
if (! (i < numList.length))
return positives;
The loop then does the test and maybe increments positives, so the recursive function should also do that:
if (numList[i] > 0) {
positives++;
}
At the end of the loop, i is updated:
i++;
The loop just starts over, but the recursive function will have to call itself. Of course, we want it to use the new value of i and positives, but fortunately we updated those, so now we can just do:
return computeSumPositives (i, numList, positives);
}
The tricky bit is that the values i, numList, and are local to each call. Each invocation of computeSumPositives can see only the arguments it were given. If it changes them, none of the other invocation can see that change.
EDIT: So if we, for reasons we can only speculate about, wanted desperately for computeSumPositive to take only 2 parameters, we would have to "split up" positives across each invocation. Each invocation knows whether or not its number was positive or not; all we have to do is add them. Then it looks like this:
computeSumPositive(int i, double[] numList)
{
if (! (i < numList.length))
return 0; // I didn't find any at index i
if (numList[i] > 0) {
// Theres one I found + however many my later
// invocations will find.
return 1 + computeSumPositive (i+1, numList);
} else {
// I didn't find any, but my later invocations might.
return computeSumPositive (i+1, numList);
}
}
I find it helpful, when dealing with recursion, to figure out the termination case first.
It looks like you are treating 'count' as an index. So you could check if your at the last index in the array, if so and if the value is positive return a 1, if the value is non-positive return a 0 - dont recurse anymore.
If your not at the last index, and the value is positive return a 1 + the recursive function call, or if the value is non-positive just continue to recurse.
This will still cause a stack overflow for large arrays.
The value of count++ is the same as the value of count; the program uses the value and then increments it. But the result is that computeSumPositive keeps calling itself with the same value of count, which leads to infinite recursion. Note that each time computeSumPositive calls another computeSumPositive, each call has its own copy of the parameters (like count) and the local variables; so incrementing one computeSumPositive's copy of count has no effect on the value of count used by other recursive calls.
Change count++ to count + 1, and also add a way to halt the recursion. (At some point, you will be calling computeSumPositive to look at zero integers, and at that point, it should just return 0 and not call itself. You need to think about: how do you test whether you've reached that point?)

Problem with recursive backtracking

Hey guys, recently posted up about a problem with my algorithm.
Finding the numbers from a set which give the minimum amount of waste
Ive amended the code slightly, so it now backtracks to an extent, however the output is still flawed. Ive debugged this considerablychecking all the variable values and cant seem to find out the issue.
Again advice as opposed to an outright solution would be of great help. I think there is only a couple of problems with my code, but i cant work out where.
//from previous post:
Basically a set is passed to this method below, and a length of a bar is also passed in. The solution should output the numbers from the set which give the minimum amount of waste if certain numbers from the set were removed from the bar length. So, bar length 10, set includes 6,1,4, so the solution is 6 and 4, and the wastage is 0. Im having some trouble with the conditions to backtrack though the set. Ive also tried to use a wastage "global" variable to help with the backtracking aspect but to no avail.
SetInt is a manually made set implementation, which can add, remove, check if the set is empty and return the minimum value from the set.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package recursivebacktracking;
/**
*
* #author User
*/
public class RecBack {
int WASTAGE = 10;
int BESTWASTAGE;
int BARLENGTH = 10;
public void work()
{
int[] nums = {6,1,2,5};
//Order Numbers
SetInt ORDERS = new SetInt(nums.length);
SetInt BESTSET = new SetInt(nums.length);
SetInt SOLUTION = new SetInt(nums.length);
//Set Declarration
for (int item : nums)ORDERS.add(item);
//Populate Set
SetInt result = tryCutting(ORDERS, SOLUTION, BARLENGTH, WASTAGE);
result.printNumbers();
}
public SetInt tryCutting(SetInt possibleOrders, SetInt solution, int lengthleft, int waste)
{
for (int i = 0; i < possibleOrders.numberInSet(); i++) // the repeat
{
int a = possibleOrders.min(); //select next candidate
System.out.println(a);
if (a <= lengthleft) //if accecptable
{
solution.add(a); //record candidate
lengthleft -= a;
WASTAGE = lengthleft;
possibleOrders.remove(a); //remove from original set
if (!possibleOrders.isEmpty()) //solution not complete
{
System.out.println("this time");
tryCutting(possibleOrders, solution, lengthleft, waste);//try recursive call
BESTWASTAGE = WASTAGE;
if ( BESTWASTAGE <= WASTAGE )//if not successfull
{
lengthleft += a;
solution.remove(a);
System.out.println("never happens");
}
} //solution not complete
}
} //for loop
return solution;
}
}
Instead of using backtracking, have you considered using a bitmask algorithm instead? I think it would make your algorithm much simpler.
Here's an outline of how you would do this:
Let N be number of elements in your set. So if the set is {6,1,2,5} then N would be 4. Let max_waste be the maximum waste we can eliminate (10 in your example).
int best = 0; // the best result so far
for (int mask = 1; mask <= (1<<N)-1; ++mask) {
// loop over each bit in the mask to see if it's set and add to the sum
int sm = 0;
for (int j = 0; j < N; ++j) {
if ( ((1<<j)&mask) != 0) {
// the bit is set, add this amount to the total
sm += your_set[j];
// possible optimization: if sm is greater than max waste, then break
// out of loop since there's no need to continue
}
}
// if sm <= max_waste, then see if this result produces a better one
// that our current best, and store accordingly
if (sm <= max_waste) {
best = max(max_waste - sm);
}
}
This algorithm is very similar to backtracking and has similar complexity, it just doesn't use recursion.
The bitmask basically is a binary representation where 1 indicates that we use the item in the set, and 0 means we don't. Since we are looping from 1 to (1<<N)-1, we are considering all possible subsets of the given items.
Note that running time of this algorithm increases very quickly as N gets larger, but with N <= around 20 it should be ok. The same limitation applies with backtracking, by the way. If you need faster performance, you'd need to consider another technique like dynamic programming.
For the backtracking, you just need to keep track of which element in the set you are on, and you either try to use the element or not use it. If you use it, you add it to your total, and if not, you proceeed to the next recursive call without increasing your total. Then, you decrement the total (if you incremented it), which is where the backtracking comes in.
It's very similar to the bitmask approach above, and I provided the bitmask solution to help give you a better understanding of how the backtracking algorithm would work.
EDIT
OK, I didn't realize you were required to use recursion.
Hint1
First, I think you can simplify your code considerably by just using a single recursive function and putting the logic in that function. There's no need to build all the sets ahead of time then process them (I'm not totally sure that's what you're doing but it seems that way from your code). You can just build the sets and then keep track of where you are in the set. When you get to the end of the set, see if your result is better.
Hint2
If you still need more hints, try to think of what your backtracking function should be doing. What are the terminating conditions? When we reach the terminating condition, what do we need to record (e.g. did we get a new best result, etc.)?
Hint3
Spoiler Alert
Below is a C++ implementation to give you some ideas, so stop reading here if you want to work on it some more by yourself.
int bestDiff = 999999999;
int N;
vector< int > cur_items;
int cur_tot = 0;
int items[] = {6,1,2,5};
vector< int > best_items;
int max_waste;
void go(int at) {
if (cur_tot > max_waste)
// we've exceeded max_waste, so no need to continue
return;
if (at == N) {
// we're at the end of the input, see if we got a better result and
// if so, record it
if (max_waste - cur_tot < bestDiff) {
bestDiff = max_waste - cur_tot;
best_items = cur_items;
}
return;
}
// use this item
cur_items.push_back(items[at]);
cur_tot += items[at];
go(at+1);
// here's the backtracking part
cur_tot -= items[at];
cur_items.pop_back();
// don't use this item
go(at+1);
}
int main() {
// 4 items in the set, so N is 4
N=4;
// maximum waste we can eliminiate is 10
max_waste = 10;
// call the backtracking algo
go(0);
// output the results
cout<<"bestDiff = "<<bestDiff<<endl;
cout<<"The items are:"<<endl;
for (int i = 0; i < best_items.size(); ++i) {
cout<<best_items[i]<<" ";
}
return 0;
}

Calculating longest path

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

Categories