第21題:
輸入兩個整數n 和m,從數列1,2,3.......n 中隨意取幾個數,使其和等於m ,要求將其中所有的可能組合列出來.
看到這樣的題目,我蒙圈了,不知道從何處下手。通過在網上搜集資料,自己終於搞定了。
先看下思路:
給定了n和m;
1.要判斷n*(n+1)/2與m的關係
如果n*(n+1)/2>m 有戲,我們可以繼續往下做,
如果n*(n+1)/2<m 沒戲了,因爲1,2,...n所有的數加起來還沒有m大呢。所以直接退出。
2.然後就是循環找數咯
循環的起始條件肯定是從 i=1開始,但是到哪裏結束呢? 循環的條件是:i<n&&i<m/2 ,這個地方就是重點了,i<n 是肯定的要有的,關鍵是後面 i<m/2;因爲如果i >=m/2 ,那麼比 i大的數在與i求和,肯定就大與m了。
3.遞歸求解
代碼:
public class Algorithm21_0 {
static void getAllComp(int n,int m){
String pre = m+"=";
int theMax = (1+n)*n/2;
if(theMax<m){
System.out.println("不存在該數!");
}else{
for(int i=1;i<n&&i<=m/2;i++){
//從1開始計數,打印出兩個數的組合,並且兩數不相等
if(i != m-i&&((m-i)<=n)){
System.out.println("here:"+pre+i+"+"+(m-i));
//continue;
}
//調用遞歸,繼續求得大於2個數的組合
getTheResult(m-i,pre+i,i,n);
}
}
}
//調用遞歸,繼續求得大於2個數的組合,j爲組合中已用過的數,所以取大於該數的。
static void getTheResult(int m,String pre,int j,int n){
for(int i=j+1;i<n&&i<=m/2;i++){
if(i != m-i&&((m-i)<=n))
System.out.println("fuck:"+pre+"+"+i+"+"+(m-i));
getTheResult(m-i,pre+"+"+i,i,n);
}
}
public static void main(String[] args) {
getAllComp(10,11);
}
}