gpt4 book ai didi

java - 回溯 - 给定一组数字,找到和等于 M 的所有子集(M 已给定)

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:58:21 24 4
gpt4 key购买 nike

正如标题所说,给定一组数字,我们必须找到总和等于给定数字(我们称之为 M)的所有子集。

你们中的大多数人可能已经熟悉这个问题,所以让我们切入正题。我最近才开始接触回溯编程(我必须告诉你,到目前为止我完全是个半身像),这就是为什么我试图解决更“经典”的问题。

现在,在下方您将看到我的代码试图以回溯方式解决此问题。但是,代码给出了

Exception in thread "main" java.lang.StackOverflowError

在第 44 行(我会突出显示它)而且,我真的不知道它是否真的以回溯方式解决了问题,或者我的代码是否只是完整和彻底的便便。

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;
}

}

注意:我希望我的评论有用,但如果它们比忽略它们更令人困惑,我认为你可以了解我在没有它们的情况下所做的事情。

尽管如此,我想知道为什么代码会给出该错误(我确实知道通常在什么情况下会给出该错误,但我不明白为什么我会在这里得到它,因为我看不到任何无限循环)以及如何使代码工作,以及它是否回溯。

最佳答案

为了在不出现堆栈溢出错误的情况下找到所有子集,我强烈建议不要使用递归。使用递归通常会在运行时产生大量开销。这种开销会导致堆栈溢出错误。您应该使用称为动态规划的更稳定的算法方法/设计。

Dynamic Programming Example应该向您展示如何利用您当前拥有的东西并将其转化为动态规划概念。

关于java - 回溯 - 给定一组数字,找到和等于 M 的所有子集(M 已给定),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41603263/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com