编写一种算法,解决解决方案给定数字的所有可能组合

时间:2016-02-01 02:24:52

标签: java algorithm list

这个想法是有一个可以多次使用的数字列表(如果解决方案是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)。

2 个答案:

答案 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:对我来说工作得很好。