This question already has answers here:
What is a StackOverflowError?
(16 answers)
Closed 6 years ago.
This is the method code:
public static void printMatrix(int[][] m, int i, int j) {
if (i == m.length ||j==m.length) {
System.out.println();
} else {
System.out.print("[" + m[i][j] + "]");
printMatrix(m, i, j++);
printMatrix(m, i++, j);
}
}
I donĀ“t know why it just prints the first position of the array until a StackOverFlow error.
Thanks for the help.
You call 2 times the recursive function, but it keep calling itself with i and j..
printMatrix(m, i, j++); << use ++j
printMatrix(m, i++, j); << use ++i
Here is a possible solution for you
public static void printMatrix(int[][] m, int i, int j)
{
System.out.print("[" + m[i][j] + "]");
if (i == m.length && j == m.length)
{
return;
}
if (j == m.length)
{
j = 0;
++i;
printMatrix(m, i, j);
}
else
{
j++;
printMatrix(m, i, j);
}
}
non-recursive
public static void printMatrix(int[][] m)
{
for (int i = 0; i < m.length; i++)
for (int j = 0; j < m.length; j++)
System.out.print("[" + m[i][j] + "]");
}
If you're trying to print each element of the matrix once, then none of the solutions in the other answers [EDIT: I guess we're down to one answer now] is going to help. The most they will do is get rid of the stack overflow error, but the output is still not going to be close to what you need.
Assuming this is a homework assignment and you've been told to use recursion for some reason (in real life nobody would do that), you have to step back and think about this: just what do you want printMatrix(m,i,j) to do? Presumably, you want to print the m[i][j] element, and then call printMatrix to print the rest of the matrix. When you call printMatrix recursively to start the printing rest of the matrix, what do you want i and j to be? Probably, you want the same i and the next column, j+1, but not if j is at the end of the row. Then you want ... I'll let you think about that. But I don't think you want printMatrix to call itself twice. Instead, you want it to call itself only once (at most); you'll probably need an if statement that looks something like
if(something)
printMatrix(something);
else
printMatrix(something different);
but it will still call itself only once (since it will pick one or the other).
I'll mention one other thing: you're comparing i to the number of rows in the array (m.length), but you're also comparing j to the number of rows in the array. That's fine if you know this is a square matrix. But if you want to compare j to the number of columns, compare it to m[i].length, since m[i] is itself an array (that represents one row of the matrix).
The size of array 'm' will be constant through out the recursive calls. Whereas the value of of i and j will be changing and base condition will be only satisfied once that. So it infinitely enter the base condition was the same i and j. That is why i guess it keeps printing only one value and after sometime the stack overflows. i do not really view this as proper use of recursion. Correct me if i'm wrong. when using recursion a problem reduces size as function calls are made till it is broken into the smallest unit possible, which can be identified by the base condition or the breaking point. I don't see this happening here.
public class Printarray {
static int max= 2;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int array[]={1,2,3};
print(array,0);
}
public static void print(int array[],int i)
{
System.out.println(array[i]);
if(i==Printarray.max)
{
Printarray.max--;
return;
}
else
{
print(array,i+1);
}
}
}
This works for 1D array, you can try this for 2D arrays and see if it works.
I hope it helps!
private static void print(int[][] mat, int i, int j) {
// TODO Auto-generated method stub
if(mat==null){
return;
}
if(i==mat.length || j==mat[0].length){
return;
}
System.out.print(mat[i][j]+" ");
if(j==mat[0].length-1){
System.out.println();
print(mat,i+1,0);
}
print(mat,i,j+1);
}
Related
public static int StringInString(String one, String two) {
if(one==null||two==null||one.equals("")||two.equals("")){
return 0;
}
else{
int x=one.length(),y=two.length(),sum=0,i=0,j=0;
char[] onee=one.toCharArray();
char[] twoo=two.toCharArray();
while(i<x){
while(j<y){
if(onee[i]==twoo[j]){
i++;
j++;
}
else{
if(j==0){
i++;
}
else{
j=0;
i++;
}
}
}
sum++;
i=i-y+1;
j=0;
}
return sum;
}
}
public static void main(String[] args){
int sum;
sum = StringInString("salamsal","sal");
System.out.println(sum);
}
hello I dont know why this ERROR apear?! please HELP me;
this code want count the similar text in two stringsa
and the result of this code should be = 2.
When you are inside the second "while" cycle, even if i > x, the cycle continues as long as j < y. So when it happens that i++ in the second cycle makes i become greater than x-1, and j is still less than y, in the first "if" (always inside the second while cycle) the program tests if onee[8] == twoo[0], and since onee[8] doesn't exist (because the indexes of "salamsal" go from 0 to 7) it shows the error that the index is out of the array bounds. To solve the error you should check for the value of i inside the second cycle, because it may happen that i++ makes this index become greater than x-1, where x is, as you declared, the length of the first string.
I need to create a Method that has 2 parameters in Java, upperborder and lowerborder. This method must create an array from the number 2 to the number 10.
Then I must implement another method, that calculates the factorial for a given number.
Then I must implement a third method that calculates the factorial for every element in the created array and test all these methods in a TestClass.
I know how to do this, but apparently I'm making some kind of a mistake in my code and it gives me the StackOverflow exception. I read the code a couple of times, but I can't seem to quite understand where I'm wrong.
package fakultaetinarray;
public final class FakultaetinArray{
private int i;
private int[] a;
private int j;
public FakultaetinArray(){
System.out.println("Given array : ");
createArray(1, 9);
System.out.println("Factorial for every element : ");
FakinArray();
}
public int fakRe(int n){
if(n == 1){
return n;
}
return n * fakRe(n - 1);
}
public void createArray(int untergrenze, int obergrenze){
this.a = new int[obergrenze];
for(this.j = 1; j <= a.length; j++){
a[i] = j + 1;
System.out.println(a[i]);
}
}
public void FakinArray(){
a[0] = 2;
for(i = 1; i < a.length; i++){
int fak = fakRe(a[i]);
a[i] = fak;
System.out.println(fak);
}
}
}
The reason you're getting StackOverflowErrors is due to your recursive method not having a case when n == 0.
The reason that your values are coming in as 0 is due to how you're constructing your loop.
for(this.j = 1; j <= a.length; j++){
a[i] = j + 1;
System.out.println(a[i]);
}
It's unclear why you're using j here at all, and i is initialized to its default value of 0, so in all reality, you're only ever filling one element of your array with a positive value and all of the others are at zero.
You need to reconsider how your loops are constructed. I would strongly encourage you not to make them fields, but declare them as part of the loop construct instead.
if(n == 1){ is not a strong enough condition to block the recursion: n can go below 1. In your particular case, you have a situation where n is 0.
Consider unwinding the recursion to a simple loop in any case. As a rule of thumb, recursion is not good for O(N) stuff.
while practicing for an exam I encountered a (for me) strange issue with quicksort.
My implementation:
public void quicksort(int l, int r)
{
if(l<r && l>0 && r<=array.length-1)
{
int pivot = array[pivot(l, r)];
int i = l;
int j = r;
if(j==i+1)
{
if(array[i]>array[j])
{
System.out.println(array[i]+"<->"+array[j]);
int help = array[i];
array[i] = array[j];
array[j] = help;
}
}
else{ while(i<=j)
{
if(array[i]>=pivot && pivot>= array[j])
{
System.out.println(array[i]+">="+pivot+">="+array[j]);
int help = array[i];
array[i] = array[j];
array[j] = help;
i++;
j--;
}
else{
i++;
}
}
if(l<j && j<array.length-1)quicksort(l, j);
if(i<r)quicksort(i, r);
}
}
}
But this is giving me a "Java.lang.StackOverflowError: null" in (here) Line 34. This Error can, however, be avoided by swapping j with j-1 and i with j in Lines 34 and 35. I really tried everything that came into my mind, but I really cannot come up with a solution :/
I think there are much better implementations of quicksort, here is my attempt with commentary which will hopefully help you remember it better:
public static void quickSort(int[] theArray, int left, int right) {
//we declare 2 variables
int i = left;
int j = right;
//we calculate a pivot, simply taking the middle value of the array
int pivot = theArray[(left+right)/2];
//check that i hasn't gone beyond j (i starts at 0, j starts at array.length)
while(i<=j){
//if here, must mean i is less-than or equal to j, so check to see if
//the array value i is less than our pivot
while(theArray[i] < pivot){
//if it is less-than pivot, the value theArray[i] is in correct place
//so we can increment i to go to next
i++;
}
//now do exactly same thing for j, however, j starts at array.length, so decrement
while(theArray[j] > pivot){
j--;
}
//if we are here, it likely means we need to swap values
//check that i hasn't gone beyond j
if(i<=j){
//simple swap
temp = theArray[i];
theArray[i] = theArray[j];
theArray[j] = temp;
//we just swapped values, so we don't need to check them again, so continue
i++;
j--;
}
}
//now check if parameter left is < j
//if left has gone beyond j, it means we no longer need to further sort
if(left<j){
//rinse and repeat
quickSort(theArray, left, j);
//and check that i is still less than right parameter
}if(i < right){
//rinse and repeat
quickSort(theArray, i, right);
}
}
Usage:
//you can amend this code so you don't have to pass in an array
quickSort(theArray, 0, theArray.length-1);
It's fairly simple once you understand what quicksort is trying to do. Don't stress out about it, take a 15minute break, watch a graphical representation of the algorithm and think about how the code should behave and what it's trying to achieve. Come back here, look at the code, and start implementing it. Rinse and repeat! Good luck!
Also (not sure how your exam layout is) but you could also mention that to near-enough guarantee runtime of O(n log n), you really ought to shuffle the array before hand.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have three for loops, and I wish to turn them into recursive method because I want to do this for any amount of for loops. I searched online, but nobody seems to have exactly what I need, for example this guy turns recursion into for loops
Turning a recursive function into a for loop?
Code:
int x = 3;
for (int i = 0; i < x; i++) {
for (int j = 0; j < x; j++) {
for (int k = 0; k < x; k++){
list.add(array[i] + array[j] + array[k]);
}
}
}
Think of a for loop as a little anonymous function that takes the loop index value as a parameter. In order to start the next iteration of the loop, the function can return a call to itself with a new value for the loop index parameter.
Like this:
Object loop(int i, Object data) {
if (i > 0) {
return loop(i - 1, evolve(data));
} else {
return data;
}
}
That's the same as this:
for ( ; i > 0; i--) {
data = evolve(data);
}
In some languages, particularly Scheme, and who knows maybe Java 8 or 9, the compiler is guaranteed to compile a recursive function such as the function loop above just the same as it compiles the for loop above.
In other languages, including the current and past versions of Java, nearly all compilers will make an executable that builds a big call stack. When the call stack is large it may even overflow the permitted size and crash the program.
Haters aside, let's do this! [1]
Given:
int x = 3;
for (int i = 0; i < x; i++) {
for (int j = 0; j < x; j++) {
for (int k = 0; k < x; k++){
list.add(array[i] + array[j] + array[k]);
}
}
}
Let's consider that each loop is it's own recursive function - as this makes the recurrence cases much easier! This is also the only "non-thinking" method I know of to turn the loops into recursion. The recursive depth will be limited to 3*x => i+j+k so it's "fairly safe" for a smallish[2] x.
In Java it requires a separate method for each loop to encode this structure. (In a language with higher-order functions these three functions might be abstractly combined .. but not in Java [7].)
void loopI(int i) {
if (i < x) {
loopJ(0); // "start j loop"
loopI(i++); // "next i loop" / recurrence case
}
// "end loop" / base case
}
void loopJ(int j) {
if (j < x) {
loopK(0);
loopJ(j++);
}
}
void loopK(int k) {
if (k < x) {
list.add(array[i] + array[j] + array[k]);
loopK(k++);
}
}
// do it!
loopI(0);
All of these could be combined into a single recursive function, but that makes handling the recurrence cases a bit tougher as "thinking" and additional conditionals (or mod expressions, perhaps) are required to advance the state.
Here is an example of a combined recursive function (this is incorrect when x is 0). Unlike the three method approach above, the stack depth will grow to x^3 => i*j*k. This will easily kill Java's recursion limits - even for smallish values of x- as Java [7] doesn't have tail-call optimization.
void loop(int i, int j, int k) {
list.add(array[i] + array[j] + array[k]);
// advance states
k++;
if (k == x) { k = 0; j++; }
if (j == x) { j = 0; i++; }
if (i == x) { i = 0; }
// terminate on all wrap-around
if (i == 0 && j == 0 && k == 0) { return; }
// recurse
loop(i, j, k);
}
[1] YMMV, for theoretical purposes only - I love recursion, but it's not suited for this case in Java.
[2] For some value of "smallish". See how deep your stack can go!
I'm in dire need of help with this project. I'm trying to implement a Bag class for a programming assignment, and I'm getting hung up on the addAll(), Union(), and equals(), methods.
Edit: According to the assignment, addAll() is supposed to add all of the the objects from the second array into the first. I'm no longer getting an error when I run it, but for some reason it will not add all of the elements from the second array, it will only add the first 2. Thanks guys, this one is working perfectly now!
Edit: For Union(), I'm supposed to create a third bag that will contain all the contents of the first 2 bags. I was getting an ArrayIndexOutOfBoundsException when running this method. I've updated the code following biddulph.r and it's also working great. Thanks again!
Edit: "First attempt" And for equals(), it's supposed to check the size of the bags to make sure they are equal in size, then check to see if they contain the same numbers. So as it's written now, my equals() method will compare sizes and return the boolean value for that, but I'm unsure of how to make it compare the actual values.
import java.util.Arrays;
import javax.swing.*;
public class bag {
int maxSize = 10; //Size of the arrays
int count = 0; //Number of items stored in the array
int[] a;
int[] b;
bag c;
bag d;
public bag() {
//for(int i = 0; i < maxSize; i++){
//a[i] = (int)(1+Math.random()*100);
//}
a = new int[maxSize];
}
public String bagString() {
return Arrays.toString(a);
}
public void add(int b) {
try {
a[count] = b;
count++;
} catch (ArrayIndexOutOfBoundsException n) {
JOptionPane.showMessageDialog(null, "Array is full, element will not be added");
}
}
public void removeRandom() {
int i = (int)(1 + Math.random() * (count - 1));
a[i] = a[count - 1];
a[count - 1] = 0;
count--;
}
public void remove(int b) {
for (int i = 0; i < maxSize; i++) {
if (contains(b)) {
a[i] = a[count - 1];
}
}
}
public boolean isEmpty() {
if (count == 0) return true;
else return false;
}
public boolean contains(int b) {
int tf = 0;
for (int i = 0; i < maxSize; i++) {
if (a[i] == b) tf = 1;
}
if (tf == 1) return true;
else return false;
}
public int size() {
return count;
}
public void addAll(bag c, bag d) {
if (a.length >= c.size() + d.size()) {
for (int i = 0; c.size() <= d.size(); i++) {
c.add(d.a[i]);
}
}
}
public void union(bag c, bag d) {
bag bigger = new bag();
for (int i = 0; i < c.size(); i++) {
bigger.add(c.a[i]);
}
for (int i = 0; count < d.size() - 1; i++) {
bigger.add(d.a[i]);
}
System.out.println(bigger.bagString());
}
public boolean equals(bag c, bag d){
if(c.size() != d.size()){
return false;
}else{
for(int i = 0; i < c.union(c, d).size(); i++){
if(c.union(c, d).contains(c.a[i]) && c.union(c, d).contains(d.a[i])){
return true;
}
}
return false;
}
}
}
I really appreciate any help you guys can give me, thanks.
EDIT: Thanks to everyone for your help, you guys are life savers.
Your problem for addAll() is here
if (a.length >= c.size() + d.size()) {
for (int i = 0; c.size() <= d.size(); i++) {
c.add(d.a[i]);
}
}
You shouldn't be adding elements until your c bag becomes bigger than d, you should be adding all of d's elements to c.
for (int i = 0; i < d.size(); i++) {
c.add(d.a[i]);
}
So the part of the assignment you are having issue with is:
public void addAll(bag c, bag d){
if (a.length >= c.size() + d.size()) {
for (int i = 0; c.size() <= d.size(); i++) {
c.add(d.a[i]);
}
}
}
which you say is supposed to add all of the the objects from the second array into the first.
If you break that down and apply it to your addAll() method, it sounds like you are supposed to be adding all of the items in bag "d" into bag "c".
Your for loop is saying start i at 0, and add 1 to it until the size of c is less than or equal to d.
What it should be saying is start i at 0, and add 1 to it until you have gone through every item in d.
That would look like this:
for (int i = 0; i < d.size(); i++){
c.add(d.a[i]);
}
i is increased every time you go through the for loop, and i will stop increasing when you have got to the size of d (the second condition). At this point you will exit the for loop. You don't have to worry about the size of c.
In fact you can probably get rid of the if (a.length >= c.size() + d.size()) line as well.
I hope my explanation helps you understand why the changes have been made to the method.
I think you have a lot of problems with the design of the class that you should address first. If you are representing the bag as a static or dynamic array then you only need one array, not 2. You also don't need two bags inside each bag as attributes, that doesn't make any sense; all you should have left is the size of the bag or count and the array to hold all the elements (which are integers in your case). Also, avoid naming parameters for functions and attributes for the class the same way. Not doing so might confuse the compiler and will require code like self.attributeName to use attributes; otherwise, the compiler assumes you're talking about the parameter.
If you make these changes, the rest should be straight-forward from here. Since it's an assignment, you should make these changes and try again because you won't learn if we provide the answers for you; you'll see it will be much easier once you structure it correctly.
P.S. it's a convention to start a class name with a capital letter. Bag and not bag
addAll
There's a couple of problems with this function as written. First is that it's confusing to the caller. The code using this method would be something like this:
Bag bag1 = ...
Bag bag2 = ...
Bag bag3 = ...
bag1.addAll(bag2, bag3)
...or perhaps bag2.addAll(bag2, bag3). The function is intended to add elements from one bag in to another bag, so why does the caller have to specify three different bags? There's only two involved. You should either make the function static, so it can be called like Bag.addAll(bag1, bag2) or (better) make it totally clear who's getting elements added by making it take a single argument bag1.addAll(bag2).
Second problem is that the function isn't implemented correctly, but I think that's because you're getting confused because you've got three bags involved instead of two. To sketch out how it should be fixed:
Bag target = ...
Bag source = ...
if (target.a.length >= target.size() + source.size()) {
for (int i = 0; i < source.a.length; i++) {
target.add(source.a[i]);
}
}
Good variable naming is your friend.
union
You haven't specified what problem you're having with your implementation, so I'm not going to simply rewrite it for you. Edit your question with the problem, and I'll help.
However, this is an excellent example of a method that should be static (a Factory method, in fact). It should be able ot be called like: Bag biggerBag = Bag.union(bag1, bag2).
EDIT after his comment regarding the .union problem
The problem with .union is that you're looping through each bag using some else's size. It boils down to, if you want add each element from source in to target, you should be only counting elements from source, as so:
bag bigger = new bag();
for (int i = 0; i <= c.size(); i++) {
bigger.add(c.a[i]);
}
note that your method does not protect against the bigger bag not being big enough. You should have a check to make sure that it is BEFORE the loops, or even better just create a big enough bag.
equals
Again, you need to show that you've tried to write it, and then ask a question specifying what you need help with. Update your question and I'll help.
Your method:
public void addAll(bag c, bag d) {
if (a.length >= c.size() + d.size()) {
for (int i = 0; c.size() <= d.size(); i++) {
c.add(d.a[i]);
}
}
}
betrays your lack of understanding of Object Oriented programming.
Remember that the method addAll() is already acting on a bag, and so you should not need to specify 2 bags in the arguments.
Calling example:
mybag.addAll(yourBag);
would demonstrate a possible usage - it would add all contents of yourBag into myBag.
I'll give you this method for free (assuming that the array 'a' contains the contents of the bag - something I'm not sure about because your variable names aren't clear):
public void addAll(Bag otherBag) {
for (int i : otherBag.a) {
add(i);
}
}
The above method will copy all contents of otherBag into this bag.
Another thing I noticed - you also have a b[] instance variable - what's that for?
You also have 2 other bag instance variables. Not sure why.