当前位置:编程学习 > JAVA >>

小于等于n的正整数相加等于m的一个算法问题

面试碰到的题,数据结构,算法什么的早忘干净了,没答上来。。。
大神看下这样做行不?
好像用什么动态规划算法挺做的,那个还没看,有会的大神帮个忙啊
/*
 * 有集合N={1,2,3……,n},求a1+a2+……+an=m(ai属于N不等于0,i=1,2,……n)的所有组合,m,n都是自然数
 */
public static void func1(int n, int m, int k, int door){
if(n>m) n = m;
if(m==1&&m>=k){
System.out.println("1");
return;
}else if(n==1){
if(m<=door)
System.out.println(m);
return;
}else {
int i = 0;
while(n*i<=m){
if(i>=k){
if(i>0)
System.out.print(i+"+");
func1(n-1,m-i,i,door);
}
i++;
}
}
}
public static void main(String[] args) {
func1(6,6,0,6);
} --------------------编程问答-------------------- 楼主,你要做什么!我什么都没有! --------------------编程问答--------------------
引用 1 楼 ganshenml 的回复:
楼主,你要做什么!我什么都没有!


就是对任意的自然数n,m,取任意多个小于等于n的自然数相加,结果等于m,求所有的这种组合。 --------------------编程问答--------------------
引用 1 楼 ganshenml 的回复:
楼主,你要做什么!我什么都没有!

上面的算法会丢掉一些元素,造成输出的表达式不全。下面的算法用数组记住以输出的表达式,再加上每次迭代后的新表达式,就不会出现上面的问题。
public class Suanfa {

/*
 * 有集合N={1,2,3……,n},求a1+a2+……+aj=m(aj属于N)的所有组合,m,n都是自然数
 */
public static void func1(int n, int m, int k, int door, int[] a){
if(n>m) n = m;
if(m==1&&m>=k){
a[a.length-n]=1;
printA(a);
return;
}else if(n==1){
if(m<=door){
a[a.length-n]=m;
printA(a);
}
return;
}else {
int i = 0;
while(n*i<=m){
if(i>=k){
if(i>0)
a[a.length-n]=i;
func1(n-1,m-i,i,door,a);
}
i++;
}
}
}
public static void printA(int[] a){
for(int i = 0; i < a.length; i++){
if(a[i]>0&&i!=a.length-1){
System.out.print(a[i]+"+");
}else if(a[i]>0){
System.out.print(a[i]);
}
}
System.out.println();
}
public static void main(String[] args) {
//func1_1(6,6,0,6);
func1(3,6,0,3,new int[3]);
}

} --------------------编程问答-------------------- 然后你上面贴代码是想说明你做出来了?求动态规划算法做? --------------------编程问答--------------------
引用 4 楼 ganshenml 的回复:
然后你上面贴代码是想说明你做出来了?求动态规划算法做?

我觉得这么做有点二笔
想求个其他好的算法,做个列子学习 --------------------编程问答--------------------
引用 5 楼 fso918 的回复:
Quote: 引用 4 楼 ganshenml 的回复:

然后你上面贴代码是想说明你做出来了?求动态规划算法做?

我觉得这么做有点二笔
想求个其他好的算法,做个列子学习
我等不搞算法,只解决实际问题,因此特来灌水! --------------------编程问答--------------------

a1  a2   a3.
0   0     0
0   0     1
0   1     0

二进制
--------------------编程问答-------------------- 6
1+5
2+4
3+3
1+1+4
2+3
2+2+2
1+1+1+3
2+2
1+1+1+1+2
1+1+1+1+1+1
这不是王晓东的那本书上的么 --------------------编程问答-------------------- 允许ai重复使用不?比如1+1+1+1=4 --------------------编程问答-------------------- 我还以为是
1+5,
2+4,
的那种? --------------------编程问答--------------------
引用 7 楼 udbwcso 的回复:

a1  a2   a3.
0   0     0
0   0     1
0   1     0

二进制

不错的想法,有时间再考虑下。如果你有代码的话能发我不?最近事太多 --------------------编程问答--------------------
引用 8 楼 Mr_WangB 的回复:
6
1+5
2+4
3+3
1+1+4
2+3
2+2+2
1+1+1+3
2+2
1+1+1+1+2
1+1+1+1+1+1
这不是王晓东的那本书上的么

什么书?求书名 --------------------编程问答--------------------
引用 9 楼 groovy2007 的回复:
允许ai重复使用不?比如1+1+1+1=4

允许 --------------------编程问答-------------------- 我感觉这个问题可以用递归求解。
将问题转换成减法 先求  m-a1是否在数组n中。如果存在ak = m-a1 则 a1+ak=m成立。接下来求解 a1-a2是否存在数组中,如果存在aj = a1-a2,则aj+a2+ak也成立。以此类推。 --------------------编程问答-------------------- 上网找个背包算法去解决这个问题. --------------------编程问答--------------------
引用 12 楼 fso918 的回复:
Quote: 引用 8 楼 Mr_WangB 的回复:

6
1+5
2+4
3+3
1+1+4
2+3
2+2+2
1+1+1+3
2+2
1+1+1+1+2
1+1+1+1+1+1
这不是王晓东的那本书上的么

什么书?求书名

算法设计与分析(第二版) --------------------编程问答--------------------
引用 14 楼 momoaiyanzi 的回复:
我感觉这个问题可以用递归求解。
将问题转换成减法 先求  m-a1是否在数组n中。如果存在ak = m-a1 则 a1+ak=m成立。接下来求解 a1-a2是否存在数组中,如果存在aj = a1-a2,则aj+a2+ak也成立。以此类推。

你这个想法就是将m分为aj+ak,然后将aj和ak分别再如此往下分为aj'、aj''和ak'、aj'',如m=6=2+4=1+1+4=2+1+3等。
如果这样的话不好去重。 --------------------编程问答--------------------
引用 17 楼 fso918 的回复:
Quote: 引用 14 楼 momoaiyanzi 的回复:

我感觉这个问题可以用递归求解。
将问题转换成减法 先求  m-a1是否在数组n中。如果存在ak = m-a1 则 a1+ak=m成立。接下来求解 a1-a2是否存在数组中,如果存在aj = a1-a2,则aj+a2+ak也成立。以此类推。

你这个想法就是将m分为aj+ak,然后将aj和ak分别再如此往下分为aj'、aj''和ak'、aj'',如m=6=2+4=1+1+4=2+1+3等。
如果这样的话不好去重。


嗯,确实存在解集重复的问题。
要完成去重的话,就需要做一些其他操作了。对每一个解集做排序,然后存Set。
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,