As the title says, we are given a set of numbers and we have to find all the subsets with a sum equal to a given number(we'll call it M).
Most of you are probably familiar with the problem already, so let's cut to the chase. I have just recently gotten into backtracking programing (I gotta tell you that I'm a complete bust so far), that's why I am trying to solve the more "classic" problems.
Now, down below you will see my code that tries to solve this problem, in a backtracking fashion. However, the code gives
Exception in thread "main" java.lang.StackOverflowError
on line 44(I shall have it highlighted) and also, I don't really know if it really solves the problem in a backtracking way or if my code is just complete and utter poop.
package project3;
import java.util.*;
public class Main {
static int[] A = { 1, 2, 3, 4 }; // the array in which we are given the numbers.->
static int n = A.length; // -> I have it filled with 1, 2, 3, 4 for testing purposes
static int m = 5; // the number which the subsets' sum must be
static int[] Sol = new int[50]; // the array in which solutions are stored up->
//->until they are syso'ed, after that it gets zero'ed
static void makeZero() { // make the solution array 0 again
for (int i = 0; i < 50; i++)
Sol[i] = 0;
}
static void show() { // outputs the solution array
int i = 0;
while (Sol[i] != 0 && i < 49) {
System.out.print(Sol[i] + " ");
i++;
}
}
public static void main(String[] args) {
Sol[0]=A[0]; back(0, 1, A[0], 1);// we start with the first number in the array as->
} // -> both the first element as the solution and part of the sum
static int back(int i, int j, int S, int nr) {
if (i < n && j < n) {
if (A[j] + S == m) {// if we got a solution, we output it and then go to the ->
Sol[nr] = A[j]; // -> next element if possible, if not, we start again with ->
show(); // -> the following element
if (j < n - 1)
back(i, j++, S, nr);
else if (i < n - 1) {
makeZero();
back(i + 1, i + 2, 0, 0);
}
}
else if (A[j] + S > m) { // condition for stoping and starting over with another element
if (j < n - 1) // we try again with the following element
back(i, j++, S, nr);// LINE 44 : Exception in thread "main" java.lang.StackOverflowError
else if (i < n - 2 && j == n - 1) { // if not possible, we start again with the following element
makeZero();
back(i + 1, i + 2, 0, 0);
} else if (i == n - 2 && j == n - 1) // if we are down to the last element->
if (A[i + 1] == m) // ->we check if it is ==m
System.out.println(A[i + 1]);
}
else if (j < n - 1 && A[j] + S < m) { // obvious
Sol[nr++] = A[j];
S = S + A[j];
back(i, j + 1, S, nr);
}
else if (j == n - 1 && A[j] + S < m && i < n - 2) {// if the sum!=m and the are no more elements->
makeZero(); // ->start again with another element
back(i + 1, i + 2, 0, 0);
}
else { // if we are down to the last element, we check if it is ==m
if(A[i+1]==n-1)
System.out.println(A[i + 1]);
}
}
return 0;
}
}
NOTE: I hope that my comments are useful, but if they are more confusing than helping just ignore them, I think that you can get an idea of what I'm doing without them.
Nevertheless, I would like to find out why is it that the codes gives that error(I do know under what context that error is generally given, I do not understand however why I get it here, as I can't see any endless loop) and how to make the code work, and also whether or not it is backtracking.
In order to find all the subsets without reaching a stack overflow error I would highly recommend staying clear of recursion. Using recursion will typically generate a lot of overhead during runtime. This overhead tneds to lead to stack overflow errors. You should use a more stable algorithmic approach/design called dynamic programming.
Dynamic Programming Example should show you how to take what you currently have and translate it to the dynamic programming concept.