《已測試通過》輸入兩個整數 n 和 m,從數列1,2,3.......n 中隨意取幾個數,使其和等於m ,要求將其中所有的可能組合列出來,並且按每個組合的字典序排列輸出,每行輸出一種組合
阿新 • • 發佈:2019-01-14
參考網上很多,瑪德都不測試的嗎?就貼出來了?浪費時間。網際網路精神在哪!!!
import java.util.ArrayList; import java.util.Comparator; import java.util.LinkedList; import java.util.Scanner; /** * [程式設計題] 求和 * 輸入兩個整數 n 和 m,從數列1,2,3.......n 中隨意取幾個數,使其和等於 m ,要求將其中所有的可能組合列出來 * 輸入描述: * 每個測試輸入包含2個整數,n和m * * 輸出描述: * 按每個組合的字典序排列輸出,每行輸出一種組合 * * 輸入例子1: * 5 5 * * 輸出例子1: * 1 4 * 2 3 * 5//注意這裡是一個數的情況 */ /** * 分析:分治的思想。可以把問題(m,n)拆分(m - n, n -1)和(m, n - 1)。 * 1.首先判斷,如果n>m,則n中大於m的數不可能參與組合,此時置n = m; * 2.將最大數n加入且n == m,則滿足條件,輸出; * 3.將n分兩種情況求解, * (1)n沒有加入,取n = n - 1; m = m;遞迴下去; * (2)n加入,取n = n - 1, m = m - n,遞迴下去 */ public class ListAllPossibleCombinationsWhichSumIsM { private static LinkedList<Integer> list = new LinkedList<>(); private static ArrayList<int[]> arrayList = new ArrayList<>(); public static void findSum(int n, int m) { if (n < 1 || m < 1) return; if (m < n) n = m;//這裡實際上完成了 n = m-n 是從遞迴一開始累計的,不單單指這層 if (m == n) { int[] temp = new int[list.size()+1]; temp[0] = m;//最小的先放進去 int index = 0; for (int i = list.size()-1; i >= 0 ; i--){//倒著裝進去 因為我們是從n開始的,也就是從大到小的遞迴,那麼list中實際上是倒序 temp[++index] = list.get(i); } arrayList.add(temp); } list.addLast(n); findSum(n - 1,m - n);//取了最後一個數,那麼和m就減去最後一個數n m-n list.removeLast(); findSum( n - 1,m);//最後一個數不可取 n沒有加入,取n=n-1,m=m } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); findSum(n,m); arrayList.sort(new Comparator<int[]>() {//字典序排序,先按照第一位,再按照第二位。。。 @Override public int compare(int[] o1, int[] o2) { if (o1[0] > o2[0]){ return 1; }else if(o1[0] < o2[0]){ return -1; }else { if (o1[1] > o2[1]){ return 1; }else if(o1[1] < o2[1]){ return -1; }else{ return 0; } } } }); for (int[] ints : arrayList) { for (int i = 0; i < ints.length; i++) { System.out.print(ints[i]); if (i != ints.length-1) System.out.print(" "); } System.out.println(); } } }