昨晚参加的网易的这次笔试,是我做过所有应聘笔试里最容易的。两个半小时,才3道题,难度较高的只有一题。
题1:printf中的if
小易刚学C语言,学了if和printf,他想自己写一个printf函数。于是他写出了如下的代码:
void myPrintf(char* format){
bool token_flag = 0;
while(true){
if(*format == '\0'){
/* Handle */
return;
}
else if(token_flag){
if(*format == 's'){
/* ... */
token_flag = 0;
}
else if(*format == 'd'){
/* ... */
token_flag = 0;
}
else if(*format == 'u'){
/* ... */
token_flag = 0;
}
else if(*format == 'p'){
/* ... */
token_flag = 0;
}
else if(*format == 'f'){
/* ... */
token_flag = 0;
}
else if(*format >= '1' && *format <= '9'){
/* ... */
}
else if(*format == '%'){
/* ... */
token_flag = 0;
}
else{
/* ... */
token_flag = 0;
}
}
else{
if(*format == '%'){
/* ... */
token_flag = 1;
}
else{
/* ... */
}
}
format++;
}
return;
}
小易不会swtich,只好用很多if else。他想知道,对于给定的语句,myPrintf函数会进行多少次if判断(else不算)。
例如,对于%2d,会进行16次if判断。
这题乍一看我头都大了。给了这么长的代码(结构是这样,注释等处不一样),不知道有什么用,而且字符串处理是我的弱项。
仔细观察,发现其实很简单。分析可知,由于每一个字符的判断次数只和它自己以及token_flag
的值有关,每个字符至多只有两种情况,那只要把字符串从前到后扫描一遍就能得出结果。
我画了一个表:
t_f | \0 | s | d | u | p | f | digit | % | other |
---|---|---|---|---|---|---|---|---|---|
0 | 1 | 3 | 3 | 3 | 3 | 3 | 3 | .3 | 3 |
1 | 1 | .3 | .4. | .5 | .6 | .7 | 8 | .9 | .9 |
t_f
表示token_flag
,第3行第3列就表示扫描到s
时会增加3次if
判断次数,小数点表示会改变token_flag
的值。
然后扫描就行了。甚至不需要用c/cpp,用Java即可。
题2:乒乓球比赛
公司里有两个部门A和B要举办乒乓球比赛。每个部门出3名男选手、3名女选手,举行男双一场、女双一场、混双一场,每人只能参加一场比赛。
部门B的小亮想知道,自己的部门有多大可能赢。为此,他给双方共计12名球手做了分析,给每个人都打了一个战力分数。他认为,一场比赛中,两个选手的战力分数加起来高的那一方会获胜,如果一样高则A部门获胜。
他希望知道,一共有多少种阵容能使得部门B获胜。定义两个阵容是不同的,当且仅当其中至少有一场比赛有一方派出了不同的选手。
乍一看又很难。仔细一想,其实每个部门只有9种阵容,因为关键在于派哪个男哪个女去参加混双,一共只有3*3种选择。
假设1、2、3为男选手,4、5、6为女选手,数组cast[6]
是1~6的一个排列,前两个选手参加男双,中间两个参加混双,后面两个参加女双,那么一个部门的所有阵容都可以用cast
来表示,而cast
只有能形成以下九种不同的阵容:
1 2 3 4 5 6
1 3 2 4 5 6
2 3 1 4 5 6
1 2 3 5 4 6
1 3 2 5 4 6
2 3 1 5 4 6
1 2 3 6 4 5
1 3 2 6 4 5
2 3 1 6 4 5
两边一共也就81种。那我全算一遍是不是就可以了……我就写了个这么暴力遍历的算法,结果就过了。
这数据还是太宽松了(窃喜)。
题3:迷宫最短路径
有一个迷宫,里面一片漆黑,不知道哪里能走、哪里不能。
但我们现在已经有了一条从起点走到终点的记录。这个记录走了很多步,有时会发现一个方向走不通,则停在原地;有时能走通,则移动位置。
现在希望根据这条记录,找出从起点到终点的最短路径的长度。请注意,如果一个位置没有被探索过,则认为是走不通的。
输入格式:
第一行是数据组数。每组数据对应一个迷宫,其第一行是路径记录的步数n
( n ⩽ 1 , 000 , 000 n \leqslant 1,000,000 n⩽1,000,000),接下来n
行每一行表示一步。一步由两个整数组成,第一个整数是{0, 1, 2, 3}之一,分别表示向上、向下、向左、向右;第二个整数是{1, -1}之一,分别表示能走通、走不通。
输出格式:
对于每组数据,输出从起点到终点的最短路径的长度。
一个很朴素的思路是,画一个巨大的地图,根据路径记录把所有能到达的地方都标出来,其他地方标为不可到达,然后广搜。
这样引出两个问题:
- 起点应该放在哪里。由于起点位置是没有给出的,后面的方向在建立地图时也是位置的,所以难以确定把起点放在哪里。最万全的方案当然是放在正中间,但那又引出第二个问题。
- 内存不够使用。即使问题1不存在,已经确定起点在迷宫左上角,由于步数的上限是一百万,为了覆盖诸如“连续往右走一百万步”的极端情况,不得不把数组开为
map[1000000][1000000]
,内存空间严重不足。那如果考虑问题1,数组又得变为原来的四倍大小,更不可能。实际上给c/cpp的空间就只有65536KB(具体数字可能不对,但肯定是万KB的数量级),给Java的也只是大概两倍而已。
我只开了个100*100的数组,想着能过一点case是一点。然而由于我脑子抽了,不用广搜用了深搜,不断地超时,过了0.00%的case。
暂时不知道怎么做。