问题描述
输入一个N,输出所有拆分的方式。如输入3
输出1+1+1
1+2
3
算法思想
用一个数组res[]存放拆分的解,用全局变量存放拆分的方法数。divN(n,k)使用n表示要分解的整数,k表示res数组下标,即第k次拆分。先从divN(n,1)开始,用num表示第k个拆分的数,即res[k]=num,让num在[1,n]内遍历。用rest=n-num表示拆分后剩下的整数值。若rest等于零,代表本次拆分结束,输出拆分解。否则处理第k+1个数组元素,即divN(rest,k+1),依次类推,直到rest为0输出结果。
数据结构
divN(int n,int k): n表示要分解的整数,k表示res数组下标,即第k次拆分。
res[10000]: 存储划分的结果,由于数组长度限制,最大的整数不能超过10000。
times : 全局变量存放拆分的方法数。
源代码
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
int res[10000] = { 0 }; //res数组存放解
int times = 0; //times计算拆分的次数
void divN(int n, int k) { //n是需要拆分的整数,k是指res数组的下标
int rest; //存放拆分后剩余的整数
for (int num = 1;num <= n; num++) { //从1开始尝试拆分
if (num >= res[k - 1] ) { //拆分的解要大于或等于前一个解保证不重复
res[k] = num; //将这次拆分存放在res数组中
rest = n - num; //剩下的是n-num
if (rest == 0) { //如果没有剩下的,说明本次拆分结束
times++; //拆分次数加1
printf("%3d:", times);
for (int j = 1; j < k; j++) { //输出解
printf("%d+", res[j]);
}//for
printf("%d\n", res[k]);
}//if
else divN(rest, k + 1); //如果有剩下的,继续求出res[k+1]
}//if
}//for
}
int main() {
int n;
printf("Please enter a integer N:");
scanf_s("%d", &n);
divN(n, 1);
printf("there are %d ways to divide the integer %d.", times,n);
system("pause");
return 0;
}
运行结果截图
存在问题及改进设想
数组长度为10000,大于10000的数就不能分解了,若要分解更大的数。方法有二:
方法一:扩大res数组的容量,如res[1000000],但这样对于较小的数拆分就十分浪费空间了。
方法二:声明一个整形指针变量int *res,和一个指向初始位置的指针int p=res,每次赋值可以为res=num,然后res++准备存储下一位分解的数。