09金山实习生笔试总结
首先说一点,感觉金山对这次实习生很不重视,连个工作人员都没派来,监考是学院的人,很囧。也没看到保密协定,所以就公开这篇日记了。
第一题是求两个整数区间的交集,即[a,b]和[c,d]的交集。这题目很简单,只要讨论端点的大小就好了。
第二题,给一个只包含字母和空格的字符串,不区分大小写,然后问那个字母没有出现过?这题目更简单,建立一个26个字母的标记表,初始化时全设置为FALSE,然后扫描字符串,出现过的字母设置为TRUE。扫描结束后再扫描一次标记表,还是FALSE的表明没有出现过。
第三题,斐波那契数列问题:
F(0)=0;F(1)=F(2)=1;F(n)=F(n-1)+F(n-2);(n>=3)。现在定义:
int v=F(n);求在v不溢出的情况下,n的最大值。
没有想到比较快的方法,就是从F(3)起开始求,判断当前值是否超过int的最大值,溢出后就结束。不过,斐波那契数列增长很快,求这个的速度不会很慢。我写的程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include "iostream" #include "cmath" #include "cstdlib" using namespace std; int main(){ int n=3; unsigned int a=1,b=1,c=2;//a保存F(n-2),b保存F(n-1),c保存F(n) unsigned int MaxInt=pow(2.0,31)-1; while(c<MaxInt){ c=a+b; a=b; b=c; ++n; } cout <<n<<endl; system("pause"); return 0; } |
运行不到1秒钟,结果为48.当时我笔试的时候犯了个低级错误,int型的最大值是2^31-1而不是2^32-1(unsigned int类型)。
第四题,哥德巴赫猜想,一个偶数必然可以表示成两个素数之和。那么现在给一个N(4<=N<=1000),求N可被表示为不同的两个素数对的个数。比如20,可以表示为(3,17)和(7,13)两对.思路也比较简单,打个素数表,然后在[2,N/2]之间的素数判断,假设当前值为i,只要判断N-i是否为素数就可以了.代码不贴了.
第五题还不错.问析构函数用虚函数有什么作用?举个例子说明这点.我对虚函数了解不多,当时感觉可能造成内存泄漏,然后就糊弄着写了下.回来后Sandy给我讲了下,才渐渐明了.
首先应该知道一点,析构函数不必要是虚函数.
其次,考虑两个问题,(1)析构函数为什么要声明为虚函数?在什么地方需要? (2)为什么析构函数要层层由子类向基类析构?
先看代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | class sth { public: ~sth(){printf("sth freed. ");} }; class A{ public: A(int a1):a(a1){s1=new sth();} virtual ~A(){printf("A:%d destroyed ",a);} virtual void F(){printf(" A(%d)::F called ",a);delete s1;} int a; sth *s1; }; class B : public A{ public : B(int a1):A(a1){s2=new sth();} virtual ~B(){printf("B:%d destroyed ",a);} virtual void F(){printf(" B(%d)::F called ",a);delete s2;} sth *s2; }; int test() { A a1(1); B b1(2); A *a2; a2=new B(3); //a2->F(); delete a2; return 0; } |
如果不将class A的析构函数声明为虚函数,那么当声明一个A *a2;时,系统知道a2是指向A对象的指针,但是你又a2=new B(3);那系统是不会知道a2实际指向了B的.此时如果delete a2时,系统只会调用A的析构函数.这就是释放一半留一半,内存泄漏了.
系统在有虚函数的时候,会建立一个虚函数表,这个表中就是一些函数指针.当a2=new B(3)时,此时a2就是指向了B的对象,因此会调用B的析构函数.
那么为什么要层层向上级析构呢? 因为每一层只管理当前层的数据的释放.虽然子类知道父类分配了些内存,但是却不知道怎么释放,或者说这事不用他管.只要层层回调析构,就可以达到释放所分配的内存.这个过程跟子类的构造函数的过程正好相反.构造函数是由基类向子类层层构造.
总结:虽然这次笔试难度很低,不过还是学到了些东西.一个是要细心,基础的概念要扎扎实实的,以后还有类似unsigned和int之类的问题.另一个是C++不仅要看,而且要多写.之前看过很多遍虚函数,换个问题就没思路了.
看完了^.^,如果觉得这篇文章对你有用或者有
问题,请留言告诉我,thank you !
文章为原创的话,转载请注明出处.不敢流泪-《09金山实习生笔试总结》
5 Comments are ready?
第一个程序非常值得推敲阿。问题很多。
关于虚析构函数,可以参见Effective C++ Item 7。
[回复]
boluor 回复 于 六月 26th, 2009 at 00:07
这题就是比较啰嗦…我花了大致上十几分钟来分类讨论.
Effective C++上那张看了.我觉得主要是我写的少.
[回复]
littlekid 回复 于 六月 26th, 2009 at 21:57
也可以参考Ruminations on C++相应条目~
[回复]
unsigned int MaxInt=pow(2.0,31)-1;
……这句也太囧了吧……………………(我估计阅卷的看到了都囧了)
你忘了你之前整理的那些位运算基础知识了么?
直白的写法: const unsigned int maxInt=~((unsigned int)0);
精简的写法:#define MAXINT (-1)
标准的写法:std::numeric_limits::max();
怎么着都轮不到动用浮点数去搞吧……
基础啊基础
[回复]
Sandy 回复 于 六月 26th, 2009 at 20:58
靠,你的blog把我的template吃了……
std::numeric_limits<unsigned int >::max()
试试这个……
[回复]
Sandy 回复 于 六月 26th, 2009 at 21:01
果然,非得我去打那个“<”这种html转义码才可以保证大于号小于号不被吃……这个wordpress转义做得太cuo了吧……
[回复]
boluor 回复 于 六月 26th, 2009 at 22:48
确实很囧…
这题不错^.^
[回复]
shit!
这题我看到过三次,第一次帮别人做(做进去了),第二次自己做(挂了),果然你们又考了一样的题目~~
[回复]
boluor 回复 于 六月 26th, 2009 at 22:47
所以说金山很不重视嘛…明天给面试通知,去玩玩好啦
[回复]
>._<
[回复]
我们的出了连分数。笔试之前搜到的都很简单,我就很放心地把浏览器关掉,快到时间才回来笔试,没想到出了一道数论的东东-_-,打我弱点。做到傻了连暴力都不敲,直接空了那题。
原来要转义才能看到的
[回复]
boluor 回复 于 七月 9th, 2009 at 09:50
连分数题目咋出的?
[回复]