程序员面试题精选{57):求n的加法组合

来源:互联网 发布:office办公软件培训班 编辑:程序博客网 时间:2024/04/29 03:56

一个正整数n可以写为几个正整数的和,如:
4=4
4=3+1
4=2+2
4=2+1+1
4=1+1+1+1
输入一个正整数,找出符合这种要求的所有正整数序列(序列不重复)

算法思想:

 
以n=6为例,将数继序列暂时存于a[MAXCOL]中,且初始时值全为1。
对数组中从jcol列开始的newn个元素进行操作f(6,0,0)  ——函数GetCombinations(newn,newj,col)
col记录调用该函数时是在第col列。
 
初始化
count=6
j=0,newn=0
count=n
1. 如果count>1,令a[jcol]=count;
         若count>a[col],表明该尝试不满足条件,count=count-1,重复1;
         否则将该行第jcol+1列到jcol+count-1列的值改为0;
    否则,退出;
2. newn=n-count
3. 如果new>1,则对从该行开始从jcol+count开始的newn个元素进行类似操作,并返回该新的newn对应的序列个数;
    否则,count=count-1,返回1。

算法比较:

“acm题目及我的程序(3)——正整数n的加法组合”——使用二维数组存放加法序列
        #define MAXROW 12000
        #define MAXCOL 20
        a[MAXROW][MAXCOL]
        算法效率低,空间浪费严重
“acm题目及我的程序(3)——正整数n的加法组合(改进)”——使用二维数组存放加法序列
        a[MAXROW][MAXCOL]
        #define MAXROW 6000
        #define MAXCOL 30
        算法效率高,空间浪费不严重
 
“acm题目及我的程序(3)——正整数n的加法组合(改进2)”——使用动态二维数组存放加法序列
        vector<vector<int> > m_venline
        算法效率高,空间浪费很少
    
  本文算法——使用一维数组存放加法序列,且计算每个n的加法序列的个数
        a[MAXCOL]
        算法效率最高,空间根本不浪费

代码如下:

 
/************************************************************************
 * 一个正整数n可以写为几个正整数的和
 * 4=4
 * 4=3+1
 * 4=2+2
 * 4=2+1+1
 * 4=1+1+1+1
 * 要求:输入一个正整数,找出符合这种要求的所有正整数序列(序列不重复)
 ***********************************************************************
*/


#include 
<stdio.h>
#include 
<string.h>
#include 
<CONIO.H>
#include 
<vector>
using namespace std;

#define MAXCOL 80
#define FILENAMELENGTH 100

class AdditionCombination
{
public:
    
int a[MAXCOL];
    
int m_number;    //条用GetCombinations函数时count的值    

public:
    AdditionCombination(
int number)
    
{
        m_number
=number;
        
for(int j=0;j<MAXCOL;j++)
            a[j]
=1;
    }


    
~AdditionCombination(){}

    
void Initialize()
    
{
        
for(int j=0;j<m_number;j++)
            a[j]
=1;
    }


    
void Initialize(int jcol)
    
{
        
for(int j=jcol;j<m_number;j++)
            a[j]
=1;
    }


    
int GetCombinations(int n,int jcol,int col);
    
void display(int n);
}
;

//在数组中从irow行,jcol列开始对n阶子矩阵进行
//col记录调用该函数前jcol的值
int AdditionCombination::GetCombinations(int n,int jcol,int col)
{
    
int nTotalCount=0;
    
int j=0,newn=0;
    
int count=n;
    
    
while(count>1)
    
{
        
if(jcol==0)
            Initialize();
        
else
            Initialize(jcol);
        a[jcol]
=count;
        
        
//算法优化,删除不满足的序列
        if(a[jcol]>a[col])
        
{
            count
--;
            
continue;
        }


        
for(j=jcol+1;j<jcol+count;j++)
            a[j]
=0;

        newn
=n-count;
        
if(newn>1)
        
{
            
int newj=jcol+count;
            
int newcount=GetCombinations(newn,newj,jcol);
            nTotalCount
+=newcount;
        }

        
        count
--;
        
//display(m_number);
        nTotalCount++;
    }


    
if(jcol==0)
    
{
        Initialize();
        
//display(m_number);
        nTotalCount++;
    }

    
else
        Initialize(jcol);

    
return nTotalCount;
}


void AdditionCombination::display(int n)
{
    printf(
"   %d=%d",n,a[0]);
    
for(int j=1;j<n;j++)
    
{
        
if(a[j])
            printf(
"+%d",a[j]);
    }

}


//将结果写入文件
void WriteToFile(vector<vector<int> > info)
{
    
char filename[FILENAMELENGTH];

    
int size=info.size();
    
//构造文件名
    sprintf(filename,"%d-%d result.txt",info[0][0],info[size-1][0]);
    FILE 
*fp=fopen(filename,"w");
    
if(fp==NULL)
    
{
        printf(
"can not wirte file!");
        exit(
0);
    }


    
//写入个数
    for(int i=0;i<size;i++)
        fprintf(fp,
"n=%d    count=%d ",info[i][0],info[i][1]);

    fclose(fp);
}


//显示菜单
void show_menu()
{
    printf(
"--------------------------------------------- ");
    printf(
"input command to test the program ");
    printf(
"   i or I : input n to test ");
    printf(
"   t or T : get count from n1 to n2 ");
    printf(
"   q or Q : quit ");    
    printf(
"--------------------------------------------- ");
    printf(
"$ input command >");
}


void main()
{
    
char sinput[10];
    
int n;

    show_menu();

    scanf(
"%s",sinput);
    
while(stricmp(sinput,"q")!=0)
    
{
        
if(stricmp(sinput,"i")==0)
        
{
            printf(
"  please input an integer:");
            scanf(
"%d",&n);

            AdditionCombination obj(n);
            
int count=obj.GetCombinations(n,0,0);
            printf(
"   count = %d ",count);
        }

        
else if(stricmp(sinput,"t")==0)
        
{
            
int n1,n2;
            printf(
"  please input the begin number:");
            scanf(
"%d",&n1);
            printf(
"  please input the  end  number:");
            scanf(
"%d",&n2);

            printf(
"  press any key to start ... ");
            getch();

            vector
<vector<int> > info;
            vector
<int> line;

            AdditionCombination obj(n1);
            
for(int i=n1;i<=n2;i++)
            
{
                obj.Initialize();
                obj.m_number
=i;
                
int count=obj.GetCombinations(i,0,0);
                printf(
"  n=%d    count=%d ",i,count);
                line.clear();
                line.push_back(i);
                line.push_back(count);
                info.push_back(line);
            }

            printf(
" ");

            
//写入文件
            printf("$ write the numbers to file(Y,N)? >");
            scanf(
"%s",sinput);
            
if(stricmp(sinput,"y")==0)        //写入文件
            {
                WriteToFile(info);
                printf(
"  write successfully! ");
            }

            printf(
" ");
        }


        
//输入命令
        printf("$ input command >");
        scanf(
"%s",sinput);
    }

}
 
原创粉丝点击