整数分解为若干项之和 Java

将一个正整数N分解成几个正整数相加,可以有多种分解方法,例如7=6+1,7=5+2,7=5+1+1,…。编程求出正整数N的所有整数分解式子。

输入格式:
每个输入包含一个测试用例,即正整数N (0<N≤30)。

输出格式:
按递增顺序输出N的所有整数分解式子。递增顺序是指:对于两个分解序列N​1​​={n​1​​,n​2​​,⋯}和N​2​​={m​1​​,m​2​​,⋯},若存在i使得n​1​​=m​1​​,⋯,n​i​​=m​i​​,但是n​i+1​​<m​i+1​​,则N​1​​序列必定在N​2
​​序列之前输出。每个式子由小到大相加,式子间用分号隔开,且每输出4个式子后换行。

输入样例:

7

输出样例:

7=1+1+1+1+1+1+1;7=1+1+1+1+1+2;7=1+1+1+1+3;7=1+1+1+2+2
7=1+1+1+4;7=1+1+2+3;7=1+1+5;7=1+2+2+2
7=1+2+4;7=1+3+3;7=1+6;7=2+2+3
7=2+5;7=3+4;7=7 

思路解析:
本题是深度优先搜索遍历的典型应用。在清华大学严蔚敏老师《数据结构》一书,第6章 图的遍历 一节中有涉及到此类遍历算法的讲解。具体内容请各位同学自行翻阅。限于篇幅,笔者仅就本题做出讨论。

深度优先搜索是一种基于递归思想而产生的一种遍历方法。如对 n = 5进行分解,我们先设计以下方案:

1 1 1 1 1   成立
1 1 1 2     成立
1 1 2 2     不成立
1 1 3       成立
1 2         不成立
1 2 2       成立
1 3 3       不成立
1 4         成立
2 2 2       不成立
2 3         成立
3 3         不成立
4 4         不成立
5           成立

观察可发现,当和大于等于n时,抛弃当前指针位,指针回到前一位并将数值进行自增,每增一次进行一次和校验;当校验结果小于n时,保留原数组,指针再向右移一位同时把前一位的值赋给当前指针位,紧接着再进行校验。直到数组中只剩下一个数且值为n时结束。

设pos为指针,array为试探数组,储存每组的试探数据,x为当前指针所指的元素。将以上思想用流程图描述如下:

Created with Raphaël 2.2.0 开始 sum < n ? array[++pos] = array[pos];sum<n? pos--;x++;sum<n? yes no

基于此我们可将判断+处理功能封装为一个函数,利用递归实现循环,示例代码如下:

import java.util.Scanner;

public class Main {
	/*
	 * 深度优先搜索遍历的应用
	 */
	 //定义全局共享变量
	static int sum = 0;//存放和
	static int pos = -1;//指针
	static int n = 0;//初始化n为0
	static int count = 0;//得到解的次数
	static int[] reslut;//试探数组

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		reslut = new int[n];
		DFS(1);

	}

	private static void DFS(int x) {
		if (sum == n) {// 得到一组解
			count++;
			System.out.print(n + "=");
			for (int i = 0; i < pos; i++) {// 输出前pos-1个元素
				System.out.print(reslut[i] + "+");
			}
			if (count % 4 == 0 || reslut[pos] == n) {// 此时换行,注意换行时不再打印分号。
			                                        //而且最后一位即 n = n时也不需要打印费分号。
				System.out.println(reslut[pos]);
			}else {
				System.out.print(reslut[pos]+";");//单独处理第pos个元素
			}
			return;// 返回上一层
		}

		if (sum > n) {// 此时是超解的
			return;// 啥都不干,直接退回上一层
		}

		for (int i = x; i < n + 1; i++) {//把i的初值赋为x,目的就是保持序列自增,防止出现(x+1)+x情况
			reslut[++pos] = i;// 要先自增再赋值,也会减少中间变量,节省空间
			sum += i;
			DFS(i);// 进入递归,其中一个就是检查作用
			pos--;// 回到初始位置
			sum -= i;// 清空该位
			
		}
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值