1. 程式人生 > >整數拆分演算法詳解

整數拆分演算法詳解

問題描述

輸入一個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++準備儲存下一位分解的數。