Java 编写一个算法,为解决方案解决给定数字的所有可能组合
其思想是,有一个可以多次使用的数字列表(如果解是5,列表是(1,4,2),那么可能的解是(1,1,1,1,1)(1,4)(1,2,2)(4,1)(2,1,1,1)(2,1,2)(2,1,2,1) 我目前的代码是:Java 编写一个算法,为解决方案解决给定数字的所有可能组合,java,algorithm,list,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,1,2,1) 我目前的代码是: static void J5(int distance, ArrayList<Integer> p) { for (int i=0; i < p.size(); i++) { int sub = (distance - p.get(i)
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);
}
}
}
因此,在这个例子中,唯一完全正确的是第一次迭代,2+2+1=5,但是下一次应该是(2,1,2)
尽管每个元素都可以多次使用,但也没有(1,1,1,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);
}
}
}
将其视为一种树。缩进显示递归深度,这相当于每个节点的级别。整个路径包含完整的解决方案。每个“找到的解决方案”将相当于代码示例输出中的一行新行
该算法工作得很好,只要找到一个有效的解决方案,它就不会打印所有找到的数字
关于代码本身的几点注意事项:代码中的第二个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));
}
}
void J5(整数距离,数组列表p,字符串解决方案){
...
如果(sub==0){
System.out.println(解决方案+“”+p.get(i));
}否则,如果(子>0){
J5(sub,p,solution+p.get(i));
}
}
至于缺少的“1”-输出:对我来说效果很好。这里我为您写了一个简洁明了的解决方案:
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);
}
}
等效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;
}
void组合sumultils(int indx、int sum、向量和候选者、向量和解、向量和结果){
if(indx==candidates.size()){
如果(总和==0)结果,则返回(解决方案);
返回;
}
如果(总和=0){
结果:推回(解决方案);
返回;
}
对于(int i=0;i=0){
解决方案。推回(候选[i]);
组合sumultils(i,sum-候选者[i],候选者,解,结果);
解决方案。弹出返回();
}否则{
打破
}
}
}
向量组合和(向量和候选,int目标){
矢量结果;
向量解;
if(candidates.size()<0)返回结果;
排序(candidates.begin()、candidates.end());
组合汇总(0,目标,候选项,解决方案,结果);
返回结果;
}
您应该引入一个新变量,并在递归期间将当前答案存储在那里,然后将其打印在sub==0
中。您所说的当前答案是什么意思?一旦调用递归,它不会丢失吗?所以将其传递给递归-添加一个新参数。这很好,但不幸您使用了错误的语言。Op我用Java解决方案更新了我的答案。谢谢:)真有趣。编码服务得到了投票,发现错误的解决方案被忽略了……我没有看到你的答案,我更欣赏你的答案而不是我的答案,我已经放弃了投票。我发现问题中的代码有点杂乱无章,这就是为什么我计划提供一个精确而清晰的代码片段。您指出了他的代码中的错误,这显然对他更有利。我认为你的回答应该被接受:)@KaidulIslam谢谢。只是觉得这种行为有点奇怪。
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
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;
}