整数拆分算法详解

问题描述

输入一个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]);
				}
				printf("%d\n", res[k]);
			}
			else divN(rest, k + 1);  //如果有剩下的,继续求出res[k+1]
		}
	}
}
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++准备存储下一位分解的数。

猜你喜欢

转载自blog.csdn.net/sysleo/article/details/83148171