简体   繁体   中英

Backtracking - Given a set of numbers, find all the subsets with a sum equal to M (M is given)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM