问题:
输入两个整数n和m,从数列1,2,3,……n中随意取几个数,使其和等于m。要求将所有的可能组合列出来
考虑一下,该怎么解决。
举例说明:
当m=5,n=4时,所有的组合为14,23
当m=6,n=5时,所有的组合为15,24,123
方法一:
遍历整个数列,从1开始,一直到n,在遍历的过程中,递归调用本方法,传入当前元素的值并+sum(初始值为0),当sum的值刚好等于m时,就打印遍历的结果。然后返回上次递归过程,继续处理下一步的执行。
整体的结构就是一个for(){}循环,再循环的内部,传入参数,继续调用本方法。直到条件满足,便打印。。
package hello.ant;
//递归回溯
public class Alog_PL_ZH3 {
static int m=10,n=10;
public static void main(String[] args) {
int result[]=new int[n];
long startTime=System.currentTimeMillis();
findResult(result, 0, 0, 0);
long endTime=System.currentTimeMillis();
System.out.println("****"+(endTime-startTime)/1000.0);
}
static void findResult(int result[],int begin,int index,int sum){
if(sum>m){
return ;
}else if(sum==m){
for(int i=0;i<index;i++){
System.out.print(result[i]);
}
System.out.println();
}else {
for(int i=begin;i<n;i++){
result[index]=i+1;//i+1表示数列对应的元素值
findResult( result, i+1, index+1, sum+i+1);
}
}
}
}
方法二:(参考了他人的思路)
背包的思想:
f(m,n)的组合情况,包含n的情况,
若将n放入背包中,那么背包的组成就为f(m-n,n-1)+n,这里的n-1,代表着元素的下标,相等于前面背包问题里面所说的物品数量,如果不将n放入背包,背包的组成就为f(m,n-1),用这种模拟的意思,来解释这种方法是什么思路。。。
代码如下:
package hello.ant;
import java.util.Stack;
public class Alog_PL_ZH4 {
static Stack<Integer> stack=new Stack<Integer>();
public static void main(String[] args) {
int m=10,n=10;
findResult(m,n);
}
static void findResult(int m,int n) {
if(m<1||n<1){
return;
}
if(m==n){
printStack();
System.out.println(n);
}
stack.add(n);
findResult(m-n, n-1);
stack.pop();
findResult(m, n-1);
}
static void printStack(){
for(Integer x:stack){
System.out.print(x+" ");
}
}
}
结果:
10
9 1
8 2
7 3
7 2 1
6 4
6 3 1
5 4 1
5 3 2
4 3 2 1