这个想法是有一个可以多次使用的数字列表(如果解决方案是5,列表是(1,4,2)那么可能的解决方案是(1,1,1, 1,1)(1,4)(1,2,2)(4,1)(2,1,1,1)(2,1,2)(2,2,1)
我目前的代码是:
static void J5(int distance, ArrayList<Integer> p)
{
for (int i=0; i < p.size(); i++)
{
int sub = (distance - p.get(i));
if (sub == 0)
{
System.out.print(p.get(i) + "\n");
return;
}
if (sub < 0)
{
sub = distance - p.get(i);
}
if (sub > 0)
{
System.out.print(p.get(i) + " ");
J5(sub, p);
}
}
}
所以基本上它是从距离5减去并使用结果的递归。我的输出是
2 2 1
1 2
4 1
1 2 2
4
因此,在这个例子中唯一完全正确的是第一次迭代为2 + 2 + 1 = 5,但接下来应该是(2,1,2) 虽然每个元素都可以多次使用,但也不存在(1,1,1,1,1)。
答案 0 :(得分:2)
在这里,我为您写了一个干净整洁的解决方案:
public class Test {
static void combinationSumUtils(int indx, int sum, ArrayList<Integer> candidates, ArrayList<Integer> solution) {
if(indx == candidates.size()) {
if(sum == 0) {
for(int i = 0; i < solution.size(); ++i) {
System.out.print(solution.get(i) + " ");
}
System.out.println();
}
return;
}
if(sum == 0) {
for(int i = 0; i < solution.size(); ++i) {
System.out.print(solution.get(i) + " ");
}
System.out.println();
return;
}
for(int i = 0; i < candidates.size(); ++i) {
if(sum - candidates.get(i) >= 0) {
solution.add(candidates.get(i));
combinationSumUtils(i, sum - candidates.get(i), candidates, solution);
solution.remove(solution.size() - 1);
} else {
break;
}
}
}
public static void main(String[] args) {
ArrayList<Integer> solution = new ArrayList<Integer>();
ArrayList<Integer> candidates = new ArrayList<Integer>();
candidates.add(1);
candidates.add(4);
candidates.add(2);
Collections.sort(candidates);
combinationSumUtils(0, 5, candidates, solution);
}
}
输出:
1 1 1 1 1
1 1 1 2
1 1 2 1
1 2 1 1
1 2 2
1 4
2 1 1 1
2 1 2
2 2 1
4 1
等效C ++解决方案:
void combinationSumUtils(int indx, int sum, vector<int> &candidates, vector<int> &solution, vector<vector<int> > &result) {
if(indx == candidates.size()) {
if(sum == 0) result.push_back(solution);
return;
}
if(sum == 0) {
result.push_back(solution);
return;
}
for(int i = 0; i < candidates.size(); ++i) {
if(sum - candidates[i] >= 0) {
solution.push_back(candidates[i]);
combinationSumUtils(i, sum - candidates[i], candidates, solution, result);
solution.pop_back();
} else {
break;
}
}
}
vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
vector<vector<int> > result;
vector<int> solution;
if(candidates.size() < 0) return result;
sort(candidates.begin(), candidates.end());
combinationSumUtils(0, target, candidates, solution, result);
return result;
}
答案 1 :(得分:1)
代码实际上有效。你只是误解了它。只需在输出中添加一些结构,您就会注意到它:
static void J5(int distance, String indent , ArrayList<Integer> p)
{
for(int i=0; i < p.size();i++)
{
int sub = (distance - p.get(i));
if (sub == 0)
{
System.out.println(indent + p.get(i)+ " Solution found" + "\n");
return;
}else if (sub > 0)
{
System.out.println(indent + p.get(i)+ " " + " distance remaining: " + sub);
J5(sub , indent + "\t" , p);
}
}
}
产生的输出将是:
1 distance remaining: 4
1 distance remaining: 3
1 distance remaining: 2
1 distance remaining: 1
1 Solution found
2 Solution found
2 distance remaining: 1
1 Solution found //Note: the complete sequence would be 1 1 2 1
2 distance remaining: 2
1 distance remaining: 1
1 Solution found
2 Solution found
4 Solution found
2 distance remaining: 3
1 distance remaining: 2
1 distance remaining: 1
1 Solution found
2 Solution found
2 distance remaining: 1
1 Solution found
4 distance remaining: 1
1 Solution found
把它看作一种树。缩进显示递归深度,它等于每个节点的级别。整个路径包含完整的解决方案。每个&#34;解决方案 - 找到&#34;将等同于代码的示例输出中的换行符。
算法运行得很好。只要找到有效的解决方案,它就不会打印整套找到的数字。
关于代码本身的一些注释:代码中的第二个if
- 子句是无用的。对sub
所做的修改在不使用的情况下被丢弃,并且没有其他修改。此算法需要排序列表作为输入,如果您想使用此代码,则必须考虑到这一点。
至于解决方案本身:只需将迄今为止生成的解决方案作为下一个调用的参数:
void J5(int distance , ArrayList<Integer> p , String solution){
...
if(sub == 0){
System.out.println(solution + " " + p.get(i));
}else if(sub > 0){
J5(sub , p , solution + p.get(i));
}
}
至于失踪&#34; 1 1 1 1 1&#34; -output:对我来说工作得很好。