演算法--中興面試:輸入兩個整數 n 和 m,從數列1,2,3.......n 中隨意取幾個數, 使其和等於 m
阿新 • • 發佈:2019-01-04
Q題目
程式設計求解
輸入兩個整數 n 和 m,從數列1,2,3…….n 中隨意取幾個數, 使其和等於 m ,要求將其中所有的可能組合列出來.
Answer解法
這道題就是一道典型的動態規劃問題了,思路和揹包問題差不多,m就相當於揹包能容納的重量了,就是從右往左校驗,通過m,以及m-n進行下一次計算。
2.1 邏輯分析
首先判斷,如果n>m,則n中大於m的數不可能參與組合,此時置n = m;
將最大數n加入且n == m,則滿足條件,直接輸出;
將n分兩種情況求解
(1)n沒有加入,取n = n-1; m = m;遞迴下去
(2)n加入,取n = n-1, m = m-n,遞迴下去
當前是 : printList( m , n )
遞迴下一層是 : printList( m , n-1 ) 和 printList( m-n , n-1 )
終止條件:n<=0,以及m<0(m<0說明在上一次遞迴呼叫是減的n,結果減多了,所以為負),m==0時候說明正好找到,列印
2.2程式碼實現
package 中興面試;
import java.util.ArrayList;
import java.util.List;
/**
* 2010 年中興面試題 程式設計求解: 輸入兩個整數 n 和 m,從數列1,2,3.......n 中隨意取幾個數, 使其和等於 m
* ,要求將其中所有的可能組合列出來.
*/
public class Test {
public static void main(String[] args) {
int n = 7;
int m = 8;
List<Integer> list = new ArrayList<>();
// 1.首先判斷,如果n>m,則n中大於m的數不可能參與組合,此時置n = m;
int up = n > m ? m : n;
printList(m, up, list);
}
/**
*
* @param m
* 要求滿足的和sum
* @param n
* 取數的範圍scope
* @param list
* 每一種滿足條件的組合
*/
public static void printList(int m, int n, List<Integer> list) {
// m=0時,即揹包剛好裝滿,列印並退出
if (m == 0) {
System.out.println(list);
return;
}
// 根據題意,可知m和n必須為正整數,所以m和n為負數,或n=0時,直接退出
if (n <= 0 || m < 0) {
return;
}
// 拿到上一次計算的結果list
List<Integer> list1 = new ArrayList<Integer>(list);
// n沒有加入
printList(m, n - 1, list);
// n加入
list1.add(n);
printList(m - n, n - 1, list1);
}
}
測試結果: