7-37 整数分解为若干项之和 (20 分)

法1:每次递归累加直至和为输入的数据

import java.util.Scanner;
public class Main {
    //计数
    static int count;
    static int index = 0;//数组的索引
    static int [] res = new int [30];//储存分解的子项,最多三十项
    static int partNum;//部分和
    static int n; //输入的数据
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        divsion(1);
    }

    static void divsion(int i) {
        if (partNum == n) {
            count++;
            System.out.printf("%d=", n);
            for (int k = 0; k < index - 1; k++) {
                System.out.printf("%d+", res[k]);
            }
            if (count % 4 == 0 || res[index - 1] == n) {
                System.out.printf("%d\n", res[index - 1]);
            } else {
                System.out.printf("%d;", res[index - 1]);
            }
        }
        else if (partNum > n) {  //累加和大于n,直接跳出
            return;
        } else {
            for (int j = i; j <= n; j++) {
                res[index++] = j;
                partNum += j;
                divsion(j); 
                partNum -= j;
                index--;
            }
        }
    }
}

最外层的循环为1~n,将每次循环分解得到的子项存储于res数组中,并让partNum加上该子项,当partNum的和等于n时,分解完成,可以输出记录的子项

缺点:会轮询很多不必要的情况,比如n=3,前两层递归已经1 1了,下一层递归循环1之后输出结果,然后会接着循环递归2和3这两种不必要的情况(正因此才会有elseif这种大于的情况)。

法2:每次递归累减直至差为0

import java.util.Scanner;
public class Main {
    //计数
    static int count;
    static int [] res = new int [30];//储存分解的子项,最多三十项
    static int n; //输入的数据
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        divsion(0, 1, n);
    }

    static void divsion(int index, int start, int num) {
        if (num == 0) {
            count++;
            System.out.printf("%d=", n);
            for (int k = 0; k < index - 1; k++) {
                System.out.printf("%d+", res[k]);
            }
            if (count % 4 == 0 || res[index - 1] == n) {
                System.out.printf("%d\n", res[index - 1]);
            } else {
                System.out.printf("%d;", res[index - 1]);
            }
        } else {
            for (int i = start; i <= num; i++) {
                res[index] = i;
                start = i;
                divsion(index + 1, start, num - i);
            }
        }
    }
}

通过减法需要三个参数,index表示res数组中的索引,start表示分解的子项的最小值(开始点),为了保证子项从小到大输出,num表示还剩余的部分。

优点:不用循环很多不必要的情况,因为算法for循环主体的起始值是在变化的,会自动抛弃那些不必要的情况,比如n=3,第一层循环i=2时,下一层循环的start>=2,但是num-i=1,该情况就不会进行运算。

在网页版答题中,两种方法都不能满足n=30时的情况,会运算超时,可能是java代码运行慢的原因吧。

参考文章:https://blog.csdn.net/wulila/article/details/108088748
https://www.cnblogs.com/andywenzhi/p/5738715.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值