正整数n的所有可能和式的组合

很多人在面试中会被问到这样的题目,题目的含义是有如下的组合4=1+1+1+1、1+1+2、1+3、2+1+1、2+2。光从题目来看有两种理解:

  1. 将3 = 1 +2 和3 = 2 +1当作不同的组合。这种情况是比较简单的,直接将给定的n递归地分解成(n – 1) + 1当递归求得的结果和我们需要分解的整数n相等,则这次分解就完成了,我们可以把分解的组合输出来,然后返回。一直递归到n不能再分解(也就是分解成了n个1)。

    #include<iostream>
    #include<vector>
    using namespace std;
    //此算法1+2与2+1当成两种不同情况
    void findadd(int sum,int start,int tempsum,vector<int> &v)
    {
    	if(tempsum == sum)
    	{
    		vector<int>::iterator it = v.begin();
    		for(;it!=v.end();it++)
    		{
    			cout<<*it;
    			if(it+1 != v.end())
    				cout<<"+";
    		}
    		cout<<endl;
    		return ;    //找到sum的组合后返回
    	}
    	else if(tempsum > sum) 
    		return ;    //大于sum时也返回
    	//进入递归
    	for(int i=sum;i>0;i--)
    	{
    		v.push_back(i);
    		findadd(sum,i,tempsum+i,v); //注意递归后第二个参数为i,第三个参数为tempsum+i.
    		v.pop_back();
    	}
    }
    
    void add(int sum)
    {
    	int tempsum =0;
    	vector<int> v;
    	findadd(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

  2. 如果把将3 = 1 +2 和3 = 2 +1当作相同的组合,这下相对来说比较难点,但是仔细分析,会发现,算法和上面的几乎一样,每次分解的数不再是从n开始,这样可以使得每次分解的数不会超过上一次分解出来的数代码只修改了一个地方就可以实现:

    #include<iostream>
    #include<vector>
    using namespace std;
    
    //此算法1+2与2+1当成相同的情况
    void findadd(int sum,int start,int tempsum,vector<int> &v)
    {
    	if(tempsum == sum)
    	{
    		vector<int>::iterator it = v.begin();
    		for(;it!=v.end();it++)
    		{
    			cout<<*it;
    			if(it+1 != v.end())
    				cout<<"+";
    		}
    		cout<<endl;
    		return ;    //找到sum的组合后返回
    	}
    	else if(tempsum > sum) 
    		return ;    //大于sum时也返回
    	//进入递归<核心>
    	for(int i=start;i>0;i--)    //这里与上一种方法的区别是i=start而不是i=sum,仅此一个区别.
    	{
    		v.push_back(i);
    		findadd(sum,i,tempsum+i,v);
    		v.pop_back();
    	}
    }
    void add(int sum)
    {
    	int tempsum =0;
    	vector<int> v;
    	findadd(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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值