今天同学笔试,碰到了一个问题:从100个数中选出任意10个数,打印出所有可能。
这是排列,组合的问题,上网查了一下,挺多这方面的资料的,这是介绍一个组合算法:
假设从0-----5中选出3个数,那么可定义一个数组,数组下标为数据值,数组存储0,1,1表示选中,0表示未选中:
1 1 1 0 0
1 1 0 1 0
1 0 1 1 0
0 1 1 1 0
1 1 0 0 1
1 0 1 0 1
0 1 1 0 1
1 0 0 1 1
0 1 0 1 1
0 0 1 1 1
根据这个算法,自己写了一个程序(但是不知道到底为什么这样,如果有谁知道,请指教):
#include <stdio.h>
#include <stdlib.h>
int * NUM; //指向实际的数值
char * NUMFLAG; //指向标志位
static int number; //存储总个数
int sum=0; //记录有多少次
#define MAXNUM 5
#define NUM(i) (*(NUM+(i))) //第i个所存储的值
#define NUMFLAG(i) (*(NUMFLAG+(i))) //表示第i个是否被选中,保存的为0,1
#define swap(x,y) do {(x)=(x)^(y);(y)=(x)^(y);(x)=(x)^(y);}while(0);
void set(int num,int Allnum) //设置小于num的为1,大于的为0
{
int i;
for(i=0;i<Allnum;i++)
{
if(i<num)
NUMFLAG(i)='1';
else
NUMFLAG(i)='0';
}
}
int init()
{
int i;
printf("there are %d number,please input the number you want to take out:\n",MAXNUM);
scanf("%d",&number);
if(number>MAXNUM)
{
printf("sorry,the number is too big!\n");
return 1;
}
NUM=(int *)(malloc(sizeof(int)*MAXNUM));
NUMFLAG=(char *)(malloc(sizeof(char)*MAXNUM));
set(number,MAXNUM);
for(i=0;i<MAXNUM;i++)
{
NUM(i)=i;
}
return 0;
}
void print()
{
int i=0;
sum++;
while(i<MAXNUM)
{
if(NUMFLAG(i)=='1')
printf("%d ",NUM(i));
i++;
}
printf("\n");
}
void assemble()
{
int j=0,k=0,number_0=0,number_1=0;
print();
do{
if(NUMFLAG(k)=='1'&&NUMFLAG(k+1)=='0')
{
swap(NUMFLAG(k),NUMFLAG(k+1)); //交换1,0
set(number_1,k); //将所有1移到最左
print();
number_1=0;
number_0=0;
k=0;
}else{ //并不是连续的1,0
if(NUMFLAG(k)=='1')
number_1++; //记录之前1的个数
else number_0++; //记录0的个数
k++;
}
}while((k+1)<MAXNUM);
}
int main()
{
init();
assemble();
printf("there are %d\n",sum);
}
#include <stdlib.h>
int * NUM; //指向实际的数值
char * NUMFLAG; //指向标志位
static int number; //存储总个数
int sum=0; //记录有多少次
#define MAXNUM 5
#define NUM(i) (*(NUM+(i))) //第i个所存储的值
#define NUMFLAG(i) (*(NUMFLAG+(i))) //表示第i个是否被选中,保存的为0,1
#define swap(x,y) do {(x)=(x)^(y);(y)=(x)^(y);(x)=(x)^(y);}while(0);
void set(int num,int Allnum) //设置小于num的为1,大于的为0
{
int i;
for(i=0;i<Allnum;i++)
{
if(i<num)
NUMFLAG(i)='1';
else
NUMFLAG(i)='0';
}
}
int init()
{
int i;
printf("there are %d number,please input the number you want to take out:\n",MAXNUM);
scanf("%d",&number);
if(number>MAXNUM)
{
printf("sorry,the number is too big!\n");
return 1;
}
NUM=(int *)(malloc(sizeof(int)*MAXNUM));
NUMFLAG=(char *)(malloc(sizeof(char)*MAXNUM));
set(number,MAXNUM);
for(i=0;i<MAXNUM;i++)
{
NUM(i)=i;
}
return 0;
}
void print()
{
int i=0;
sum++;
while(i<MAXNUM)
{
if(NUMFLAG(i)=='1')
printf("%d ",NUM(i));
i++;
}
printf("\n");
}
void assemble()
{
int j=0,k=0,number_0=0,number_1=0;
print();
do{
if(NUMFLAG(k)=='1'&&NUMFLAG(k+1)=='0')
{
swap(NUMFLAG(k),NUMFLAG(k+1)); //交换1,0
set(number_1,k); //将所有1移到最左
print();
number_1=0;
number_0=0;
k=0;
}else{ //并不是连续的1,0
if(NUMFLAG(k)=='1')
number_1++; //记录之前1的个数
else number_0++; //记录0的个数
k++;
}
}while((k+1)<MAXNUM);
}
int main()
{
init();
assemble();
printf("there are %d\n",sum);
}
posted @ 2009-04-10 19:48 yangbinhe 阅读(110) 评论(0) 编辑
1、有一个整形数组,其元素包含正整数和负整数,找到它的所有子集中元素之和最大的那个子集。
如:[12,-3,54,-42,4,5,7],结果为63[12,-3,54]。
要求复杂度为O(n)。
int func(int n, int a[])
{
int sum = 0, b = 0, i;
for (i = 1; i <= n; i++)
{
if (b>0) b+=a[i];
else b=a[i];
if (b>sum) sum = b;
}
return sum;
}
{
int sum = 0, b = 0, i;
for (i = 1; i <= n; i++)
{
if (b>0) b+=a[i];
else b=a[i];
if (b>sum) sum = b;
}
return sum;
}
2、求乱序排序的N个数中连续K个数的和的最大值。
具体思路:
假设有N个数:a1 a2 a3 a4 a5 ... aN
需要求出所有连续K个数的和,那么,先求出a1~ak的和sum
a(2)~a(k+1)的和=sum - a1 + a(k+1)---------------------(1)
a(3)~a(k+2)的和=(1)式结果-a(2) + a(k+2)
posted @ 2009-04-10 17:22 yangbinhe 阅读(291) 评论(0) 编辑

