整數拆分演算法詳解
阿新 • • 發佈:2018-11-10
問題描述
輸入一個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++準備儲存下一位分解的數。