很多人在面试中会被问到这样的题目,题目的含义是有如下的组合4=1+1+1+1、1+1+2、1+3、2+1+1、2+2。光从题目来看有两种理解:
将3 = 1 +2 和3 = 2 +1当作不同的组合。这种情况是比较简单的,直接将给定的n递归地分解成(n - 1) + 1当递归求得的结果和我们需要分解的整数n相等,则这次分解就完成了,我们可以把分解的组合输出来,然后返回。一直递归到n不能再分解(也就是分解成了n个1)。
#include <iostream> #include <vector> // 过往记忆 // www.iteblog.com // 转载请注明 using namespace std; void add(int sum, int start, int tempSum, vector<int> &v){ if(sum == tempSum){ vector<int>::iterator it = v.begin(); for(; it != v.end(); it++){ cout << *it; if(it + 1 != v.end()){ cout << " + "; } } cout << endl; return; }else if(sum < tempSum){ return; } for(int i = sum; i > 0; i--){ v.push_back(i); add(sum, i, tempSum + i, v); v.pop_back(); } } void add(int sum){ int tempSum = 0; vector<int> v; add(sum, sum, tempSum, v); } int main(){ add(5); return 0; }
运行的结果:
5 4 + 1 3 + 2 3 + 1 + 1 2 + 3 2 + 2 + 1 2 + 1 + 2 2 + 1 + 1 + 1 1 + 4 1 + 3 + 1 1 + 2 + 2 1 + 2 + 1 + 1 1 + 1 + 3 1 + 1 + 2 + 1 1 + 1 + 1 + 2 1 + 1 + 1 + 1 + 1
如果把将3 = 1 +2 和3 = 2 +1当作相同的组合,这下相对来说比较难点,但是仔细分析,会发现,算法和上面的几乎一样,每次分解的数不再是从n开始,这样可以使得每次分解的数不会超过上一次分解出来的数,代码只修改了一个地方就可以实现:
#include <iostream> #include <vector> // 过往记忆 // www.iteblog.com // 转载请注明 using namespace std; void add(int sum, int start, int tempSum, vector<int> &v){ if(sum == tempSum){ vector<int>::iterator it = v.begin(); for(; it != v.end(); it++){ cout << *it; if(it + 1 != v.end()){ cout << " + "; } } cout << endl; return; }else if(sum < tempSum){ return; } for(int i = start; i > 0; i--){//和上面的程序相比,只修改了这个地方 v.push_back(i); add(sum, i, tempSum + i, v); v.pop_back(); } } void add(int sum){ int tempSum = 0; vector<int> v; add(sum, sum, tempSum, v); } int main(){ add(5); return 0; }
程序运行结果:
5 4 + 1 3 + 2 3 + 1 + 1 2 + 2 + 1 2 + 1 + 1 + 1 1 + 1 + 1 + 1 + 1本博客文章除特别声明,全部都是原创!
原创文章版权归过往记忆大数据(过往记忆)所有,未经许可不得转载。
本文链接: 【正整数n的所有可能和式的组合】(https://www.iteblog.com/archives/452.html)