【编程题目】输入两个整数 n 和 m,从数列 1,2,3.......n 中 随意取几个数, 使其和等于 m ... ★

第 21 题(数组)
2010 年中兴面试题
编程求解:
输入两个整数 n 和 m,从数列 1,2,3.......n 中 随意取几个数,
使其和等于 m ,要求将其中所有的可能组合列出来.

 

我的思路:

从小到大 依次拼凑 后面选的数字 必须比前面大 保证不重复
如: n = 4 m = 8
1 2 3 4 超过8 去掉最后一个数 导数第二个数加一
1 2 4 小于8 最后一个数等于 4 去掉最后一个数 导数第二个数加一
1 3 4 符合 输出 最后一个数等于 4 去掉最后一个数 导数第二个数加一
1 4 小于8 最后一个数等于 4 去掉最后一个数 导数第二个数加一
2 3 小于8
2 3 4 超过8 去掉最后一个数 导数第二个数加一
2 4 小于8 最后一个数等于 4 去掉最后一个数 导数第二个数加一
......

 

代码:

/*
第 21 题(数组)
2010 年中兴面试题
编程求解:
输入两个整数  n  和  m,从数列 1,2,3.......n  中  随意取几个数,
使其和等于  m ,要求将其中所有的可能组合列出来.
start time = 15:55
end time = 17:03
*/

#include <iostream>
using namespace std;


int FindCombine(int n, int m)
{
    int method = 0; //一共有多少方法
    if(m <= 0)
    {
        return 0;
    }
    else
    {
        int record[100]; //存储组合当前的取值
        for(int i = 0; i < 100; i++)
        {
            record[i] = i + 1;
        }
        int num = 0; //组合中数字的个数
        int sum = 0; //组合中数字加起来的和

        while(sum < m)
        {
            sum += record[num];
            num++;

            if(sum == m)
            {
                method++;
                printf("组合%d:", method);
                for(int i = 0; i < num; i++)
                {
                    printf("%d ", record[i]);
                }
                printf("\n");

                if(num == 1)
                {
                    return method;
                }
            }
            if((sum >= m) || (sum < m && record[num - 1] == n && num >= 2)) //如果大小超过m 或者 最后一个数字大小等于n 更新record
            {
                num--;
                sum -= record[num];
                num--;
                sum -= record[num];
                if(record[num] <= n)
                {
                    record[num]++;
                    for(int i = 1; i <= n - record[num]; i++)
                    {
                        record[i + num] = record[num] + i;  
                    }
                }
            }
            else if(sum < m && record[num - 1] == n && num == 1)
            {
                return method;
            }
        }
    }
}



int main()
{
    int w = FindCombine(50, 100);
    return 0;
}

 

惯例上网找别人的方法, 一看我就郁闷了, 居然可以用动态规划, 我的算法算是白学了, 到用的时候一点都想不起来。

http://blog.sina.com.cn/s/blog_7571423b01016707.html 里有个详细的分析

http://www.cnblogs.com/freewater/archive/2012/07/16/2593218.html 里有非常精简的代码

vector<int> factors;
void findFactor2(int sum,int n){
    if(sum<0||n<0)
        return ;
    if(sum==0){
        for(vector<int>::iterator iter=factors.begin();iter!=factors.end();++iter){
            cout<<*iter<<' ';
        }
        cout<<endl;
        return;
    }

    factors.push_back(n);//典型的01背包问题  
    findFactor2(sum-n,n-1);//放n,n-1个数填满sum-n 
    factors.pop_back();
    findFactor2(sum,n-1);//不放n,n-1个数填满sum   
}

 

posted @ 2014-08-05 21:28  匡子语  阅读(5020)  评论(1编辑  收藏  举报