首先,说明一下,很长时间没来写博客了,是的,前段时间忙考研,耽误了半年多,现在,考研初试成绩出来了,现在正准备复试,由于不冲突,我就在准备c/c++的复试,顺便写写自己的技术blog。我一直这样认为,写blog可以加深自己对知识的理解。言罢,今天写了来两个小算法,算是熟悉一下语言的应用。
关于和序列问题,即形如(数据不重复)
10=1+2+3+4
10=1+2+7
10=1+3+6
10=1+4+5
10=1+9
10=2+3+5
10=2+8
10=3+7
10=4+6
const int N = 10; /* test number */
/* print the numbers */
void print(int *list, int num)
{
int i;
cout<<N<<"="<<list[0];
for(i = 1; i < num; i ++)
cout<<"+"<<list[i];
cout<<endl;
}
/* key function here */
void getNumList(int sum, int begin,int *list ,int i)
{
int next;
list[i] = begin;
i++;
sum -= begin;
if(sum == 0) print(list,i);// be found
else
{
//continue searching the next number
for(next = begin+1; next <= sum; next++)
getNumList(sum,next,list,i);
}
}
int main(void)
{
int sum = N, begin;
int list[N/2];
/* test all beginings */
for(begin = 1; begin <= sum/2; begin ++)
getNumList(sum,begin,list,0);
return 0;
}
很容易理解,不错解释。
还有一道很老的腾讯面试题,类似题型:
写道
上个星期去腾讯面试一位主考官出的动脑题,当时被难住了,自己确实笨死了,麻烦高手帮解答下具体的计算思路。
题目如下:
给你10分钟时间,根据上排给出十个数,在其下排填出对应的十个数
要求下排每个数都是先前上排那十个数在下排出现的次数。
上排的十个数如下:
【0,1,2,3,4,5,6,7,8,9】
题目如下:
给你10分钟时间,根据上排给出十个数,在其下排填出对应的十个数
要求下排每个数都是先前上排那十个数在下排出现的次数。
上排的十个数如下:
【0,1,2,3,4,5,6,7,8,9】
例如:写道
####################
数值:0,1,2,3,4,5,6,7,8,9
分配:6,2,1,0,0,0,1,0,0,0
比如说,
0的下面我填写6,就表示在下面一共有6个0.
1的下面我填写2,表示下面下面一共有2个1
2的下面我填写1,表示下面下面一共有1个2
数值:0,1,2,3,4,5,6,7,8,9
分配:6,2,1,0,0,0,1,0,0,0
比如说,
0的下面我填写6,就表示在下面一共有6个0.
1的下面我填写2,表示下面下面一共有2个1
2的下面我填写1,表示下面下面一共有1个2
算法如下:
const int N = 10;
const int s[N] = {0,1,2,3,4,5,6,7,8,9};
/* repair the result list */
void repair(int *array)
{
int sum = 0;
for(int i = 1; i < N; i++)
sum += array[i];
array[0] = N - sum;
}
/* test the result list */
int isRight(int *r)
{
int i,j,sum;
for(i = 0; i < N; i++)
{
sum = 0;
//test the i number
for(j = 0; j < N; j++)
if(r[j] == s[i]) sum ++;
if(sum != r[i])//not match
return 0;
}
return 1;
}
/* print the right result list */
void print(int *array)
{
int i = 0;
for(; i < N; i++) cout<<array[i]<<" ";
cout<<endl;
}
/*
* key function
* serach from N to 0
* constrict 1
*/
void getSerial(int sum, int *result, int num)
{
int i;
/* case 1*/
if(num == 0 && sum != 0) return;
// not match here
/* case 2*/
if(sum == 0) // out of use
{
for(i = num; i > 0; i--) result[i] = 0;
// important point for result[0]:constrict 2
repair(result);
if(isRight(result)) //constrict 3
{
print(result);
return;
}
else return;
}
/* case 3*/
for(i = 0;i*s[num] <= sum; i++)
{
result[num] = i;
getSerial(sum-i*s[num],result,num-1);
}
}
可以注意到 该序列有三个限制条件(程序中也用constrict表示出来)
constrict 1: 就是两数组对乘的结果是N
由于该条件限制较强,好理解,所以用作循环条件,以便减少遍历次数
constrict 2:repair()修正0的个数(比较特殊)待改善
constrict 3:就是检验是s【】中个数是否和人r【】中的对应(最强限制,但最难利用理解)