题目描述
输入两个整数 n 和 m,从数列1,2,3.......n 中随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来
输入描述:
每个测试输入包含2个整数,n和m
输出描述:
按每个组合的字典序排列输出,每行输出一种组合
示例1
输入
5 5
输出
1 4
2 3
5
1 import java.util.Collection; 2 import java.util.Collections; 3 import java.util.LinkedList; 4 import java.util.Scanner; 5 6 /** 7 * 分析: 8 * 1、一个数时表示: 9 * 只有 n>m 时 才会有 n内的一个数等于m,可以最后判断考虑 10 * 2、两个数时: 11 m=1+(m-1)=2+(m-2)=i+(m-i)控制(i<m-i),如果(m-i<n)那么这一组数字满足要求,添加进入list, 12 * 3、三个数时: 13 * 三个数就是把两个数中较大的数拆分,要增加数字数量,不会出现 m = n 的情况 ,而为了避免重复,较小的数也必须从i+1开始 14 * 那么就是 (i+1)--(m-i-1)范围内查找,用i+1替代i 用m-i-1替代m 循环控制(i< m-i)寻找满足要求的数。 15 ... 16 ... 17 解题: 18 1、递归查找 19 2、解决一个数问题 20 3、排序 21 4、输出 22 */ 23 public class Main { 24 static public LinkedList<String> res = new LinkedList(); 25 static public void f(int p/*记录小数字避免重复*/,int n,int m,String rstr/*已经选出的小数字*/) { 26 // 每次从 p等于上层的i+1开始循环 27 for (int i = p; i <m-i; i++) { 28 if (m-i<=n/*两个数中较大的数小于n说明都在范围内*/) { 29 //符合范围 保存: 上一层较小的数+拆分后的小数+拆分后的大数 30 String s=(rstr+" "+i+" "+(m-i)).trim(); 31 res.add(s); 32 } 33 /* 递归 */ 34 f(i+1, n,m-i/* m */, rstr+" "+i/*将小数保存,拆分大数*/); 35 } 36 } 37 public static void main(String[] args) { 38 Scanner sc = new Scanner(System.in); 39 int n = sc.nextInt(); 40 int m = sc.nextInt(); 41 // 递归查找 42 f(1, n, m,""); 43 // 处理 m=n 44 if (m<=n) res.add(m+""); // 最后处理 m==n 时的一 45 res.sort(null); // 排序 46 for (String string : res) { 47 System.out.println(string); 48 } 49 } 50 }