Why are these statements equal? Stack methods in java - java

Why are the following statements equivalent? emptyRow and emptyCol are Integer stacks, and Grid is a two dimensional array of integers. There is no need for you to know what the program does, but in case you're wondering it's a sudoku puzzle solving algorithm that uses basic back-tracking.
Both statements allow the program to run without any bugs, but I don't understand how this is possible since .pop() returns the top most integer in the first implementation, while the second one first pops the top most items and retrieves the integers directly under those.
Statement A:
Grid[emptyRow.pop()][emptyCol.pop()] = 0;
Statement B:
emptyRow.pop();
emptyCol.pop();
Grid[emptyRow.peek()][emptyCol.peek()] = 0;
Sorry if this is a silly logic problem with my code, I'm just checking to see if there is something I don't know about how stack operations work.

Statement A is the same as
Grid[emptyRow.peek()][emptyCol.peek()] = 0;
emptyRow.pop();
emptyCol.pop();
I think you have the order confused, and perhaps in your use case it doesn't matter but the code is not the same.

Related

Figuring out The Big O Notation/Recurrence Relation From My Old Algorithm

**Hi all,
I have a question about recurrence relation/ Big O notation. I was given a homework assignment that asked me to give the Big O notation of some of my old code/ Algorithms that I came up with for previous homework assignments. Sadly, I have not yet taken a course in Finite Mathematics; so this is new to me. I managed to figure out three of the four Algorithms that I used. However, I am stuck on the fourth algorithms. This method is a recursive method and is coded in Java. I have, really, spent hours trying to figure this out, and I’ve watched lots of videos and read lots of articles on Big O notation but sadly can’t get it. Any help would be great!!!
Here is the code:
ArrayList<FacebookUser> getRecommendations(FacebookUser e) {
FacebookUser rootUser = userCallForList.get(0);
if(rootUser.getFriends().isEmpty() || e.getFriends().isEmpty()){
return returnHash();
}
for(FacebookUser hold : e.getFriends()){
if( !hold.equals(rootUser) && addHash(hold)){
getRecommendations(hold);
}
}
return returnHash();
}
Note About the Code:
The method takes a FacebookUser as an argument. The method returns an ArrayList that contains all of the friends of the FacebookUser that is passed into it plus the result of calling the same getRecommendations method on all of that FacebookUser’s friends. It does not add anyone to the list of recommendations if they are already on it and does not add the FacebookUser (E.I rootUser) that is calling it; As that could lead to an infinite loop. I use a HashSet as my collection and then I have to change it back to an ArrayList.
If I'm understanding your code right then this isn't a traditional recurrence because n (the input size) changes on each recursive call but does not necessarily get smaller i.e. it's not a divide and conquer algorithm.
This statement
for(FacebookUser hold : e.getFriends()){
if( !hold.equals(rootUser) && addHash(hold)){
getRecommendations(hold);
}
}
calls getRecommendations() for an unspecified number of friends which then calls it for each friend's friends. To me it seems like this method would be called for every friend in the network or every node if you think of it as a graph problem. This implies to me a running time O(k) where k = number of unique nodes reachable from the initial user by any number of edges.

How do you create a mathematical sequence in Java?

I want to declare integers, while the program is running.
I run the program, and then I give it via System.in.println an integer and repeat this as long as I want.
I want the program to give those integers a name of a certain type for, for example a(i) or a[i], dunno, (it should be handy) and then a(i) represents the the i'th integer I gave the program.
My idea is then that I can use those elements by their name just like, if I had declared them in the first place.
For example add two integers together.
For example I defined a method add+, which waits for 2 integer and then adds them. For example I write:
add
a(2)
a(47)
(then I would get here the result.)
I don't think implementing the add function is difficult. However I don't know, how to let the program count the number of inputs or how to let it declare and use variables.
First: Welcome to programming java; it will be a long road.
Here are some hints:
Use a List<Integer> to hold the sequence of numbers entered by the user.
Actually instanciate a concreate List class, for example LinkedList<Integer>'. If you need to access the elements by index, use anArrayList`.\
Each time the user enters a number, create a new Integer and userList.add(newInteger);
Simple sample
List<Integer> userList = new LinkedList<Integer>();
for (index = 0; index < 9; ++index)
{
Integer newInteger = new Integer(index);
userList.add(newInteger);
}
for (Integer current : userList)
{
System.out.println(current);
}
Yeah, I am following the conversation.
I am just a bit frustrated, because I can't really write any interesting or practical java programs (yet), because my knowledge isn't that big yet.
First I tried to find out, if there was a way to add elements to array, because arrays seemed to me very useful, because each element of an array already has an address. I googled, and it seems that is not possible.
I might be able to use the idea with the list, but it seems to be that the length of the list has to have a limit and actually I wanted to avoid that.

How do you (get around) dynamically naming variables?

I'm not sure if I'm using the right nomenclature, so I'll try to make my question as specific as possible. That said, I imagine this problem comes up all the time, and there are probably several different ways to deal with it.
Let's say I have an array (vector) called main of 1000 random years between 1980 and 2000 and that I want to make 20 separate arrays (vectors) out of it. These arrays would be named array1980, array1981, etc., would also have length 1000 but would contain 1s where the index in the name was equal to the corresponding element in main and 0s elsewhere. In other words:
for(int i=0; i<1000; i++){
if(main[i]==1980){
array1980[i]=1;
} else {
array1980[i]=0;
}
Of course, I don't want to have to write twenty of these, so it'd be good if I could create new variable names inside a loop. The problem is that you can't generally assign variable names to expressions with operators, e.g.,
String("array"+ j)=... # returns an error
I'm currently using Matlab the most, but I can also do a little in Java, c++ and python, and I'm trying to get an idea for how people go about solving this problem in general. Ideally, I'd like to be able to manipulate the individual variables (or sub-arrays) in some way that the year remains in the variable name (or array index) to reduce the chance for error and to make things easier to deal with in general.
I'd appreciate any help.
boolean main[][] = new boolean[1000][20];
for (int i=0; i < 1000; i++) {
array[i][main[i]-1980] = true;
}
In many cases a map will be a good solution, but here you could use a 2-dim array of booleans, since the size is known before (0-20) and continuous, and numerable.
Some languages will initialize an array of booleans to false for every element, so you would just need to set the values to true, to which main[i] points.
since main[i] returns numbers from 1980 to 2000, 1980-main[i] will return 1980-1980=0 to 2000-1980=20. To find your values, you have to add 1980 to the second index, of course.
The general solution to this is to not create variables with dynamic names, but to instead create a map. Exactly how that's done will vary by language.
For Java, it's worth looking at the map section of the Sun collections tutorial for a start.
Don Roby's answer is correct, but i would like to complete it.
You can use maps for this purpose, and it would look something like this:
Map<Integer,ArrayList<Integer>> yearMap = new HashMap<Integer,ArrayList<Integer>>();
yearMap.put(1980,new ArrayList<Integer>());
for (int i = 0; i < 1000; i++){
yearMap.get(1980).add(0);
}
yearMap.get(1980).set(999,1);
System.out.println(yearMap.get(1980).get(999));
But there is probably a better way to solve the problem that you have. You should not ask how to use X to solve Y, but how to solve Y.
So, what is it, that you are trying to solve?

Stack Overflow Error java

I'm trying to solve a problem that calls for recursive backtracking and my solution produces a stackoverflow error. I understand that this error often indicates a bad termination condition, but my ternimation condition appears correct. Is there anything other than a bad termination condition that would be likely to cause a stackoverflow error? How can I figure out what the problem is?
EDIT: sorry tried to post the code but its too ugly..
As #irreputable says, even if your code has a correct termination condition, it could be that the problem is simply too big for the stack (so that the stack is exhausted before the condition is reached). There is also a third possibility: that your recursion has entered into a loop. For example, in a depth-first search through a graph, if you forget to mark nodes as visited, you'll end up going in circles, revisiting nodes that you have already seen.
How can you determine which of these three situations you are in? Try to make a way to describe the "location" of each recursive call (this will typically involve the function parameters). For instance, if you are writing a graph algorithm where a function calls itself on neighbouring nodes, then the node name or node index is a good description of where the recursive function is. In the top of the recursive function, you can print the description, and then you'll see what the function does, and perhaps you can tell whether it does the right thing or not, or whether it goes in circles. You can also store the descriptions in a HashMap in order to detect whether you have entered a circle.
Instead of using recursion, you could always have a loop which uses a stack. E.g. instead of (pseudo-code):
function sum(n){
if n == 0, return 0
return n + sum(n-1)
}
Use:
function sum(n){
Stack stack
while(n > 0){
stack.push(n)
n--
}
localSum = 0
while(stack not empty){
localSum += stack.pop()
}
return localSum
}
In a nutshell, simulate recursion by saving the state in a local stack.
You can use the -Xss option to give your stack more memory if your problem is too large to fix in the default stack limit size.
As the other fellas already mentioned, there might be few reasons for that:
Your code has problem by nature or in the logic of the recursion. It has to be a stoping condition, base case or termination point for any recursive function.
Your memory is too small to keep the number of recursive calls into the stack. Big Fibonacci numbers might be good example here. Just FYI Fibonacci is as follows (sometimes starts at zero):
1,1,2,3,5,8,13,...
Fn = Fn-1 + Fn-2
F0 = 1, F1 = 1, n>=2
If your code is correct, then the stack is simply too small for your problem. We don't have real Turing machines.
There are two common coding errors that could cause your program to get into an infinite loop (and therefore cause a stack overflow):
Bad termination condition
Bad recursion call
Example:
public static int factorial( int n ){
if( n < n ) // Bad termination condition
return 1;
else
return n*factorial(n+1); // Bad recursion call
}
Otherwise, your program could just be functioning properly and the stack is too small.

Java Binary search

Trying to perform a binary search on a sorted array of Book objects.
Its not working well, it returns the correct results for some of the objects, but not all.
I went through the loop on paper and it seems that a number can get missed out due to rounding #.5 upwards.
Any ideas how to make this work?
Book found = null;
/*
* Search at the center of the collection. If the reference is less than that,
* search in the upper half of the collection, else, search in the lower half.
* Loop until found else return null.
*/
int top = numberOfBooks()-1;
int bottom = 0;
int middle;
while (bottom <= top && found == null){
middle = (bottom + top)/2;
if (givenRef.compareTo(bookCollection.get(middle).getReference()) == 0) {
found = bookCollection.get(middle);
} else if (givenRef.compareTo(bookCollection.get(middle).getReference()) < 0){
bottom = middle + 1;
} else if (givenRef.compareTo(bookCollection.get(middle).getReference()) > 0){
top = middle - 1;
}
}
return found;
A couple suggestions for you:
there's no need to keep a Book variable. In your loop, just return the book when it's found, and at the end return null. And you can also remove the boolean check for the variable in the while condition.
the middle variable can be scoped inside the loop, no need to have it live longer.
you're doing bookCollection.get(middle).getReference() three times. Consider creating a variable and then using it.
the middle = (bottom + top)/2 is a classic mistake in binary search implementation algorithms. Even Joshua Bloch, who wrote the Java Collection classes, made that error (see this interesting blog post about it). Instead, use (bottom+top) >>> 1, to avoid integer overflow for very large values (you probably wouldn't encounter this error, but it's for the principle).
As for your actual problem statement, rounding would be downwards (integer division), not upwards. To troubleshoot the problem:
are you sure the numberOfBooks() method corresponds to the length of your collection?
are you sure the compareTo() method works as expected for the types you are using (in your code example we do not know what the getReference() return type is)
are you sure your collection is properly sorted according to getReference()?
and finally, are you sure that using givenRef.compareTo(bookCollection.get(middle).getReference()) < 0 is correct? In standard binary search implementations it would be reversed, e.g. bookCollection.get(middle).getReference().compareTo(givenRef) < 0. This might be what donroby mentions, not sure.
In any case, the way to find the error would be to try out different values and see for which the output is correct and for which it isn't, and thus infer what the problem is. You can also use your debugger to help you step through the algorithm, rather than using pencil and paper if you have to run many tests. Even better, as donroby said, write a unit test.
What about Collections.binarySearch()?
All of JRL's suggestions are right, but the actual fail is that your compares are reversed.
I didn't see this immediately myself, but replicating your code into a function (using strings instead of Books), writing a some simple Junit tests and then running them in the debugger made it really obvious.
Write unit tests!
I found the problem.
It turns out i was binary searching my bookCollection arrayList, and NOT the new sroted array i had created - sortedLib.
Silly mistake at my end, but thanks for the input and suggestions!

Categories