求和

题目描述

输入两个整数 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 }

猜你喜欢

转载自www.cnblogs.com/the-wang/p/8981336.html