搜尋
首頁後端開發php教程腾讯C++后台招聘问题汇总与分享_PHP教程

腾讯C++后台招聘问题汇总与分享

1.前言

2016.4.11日广州天河区东圃喜来登酒店参加了Tencent CC++后台技术一面,面试官人很温和,经历了大概70分钟的问答,特将遇到的面试问题汇总如下,自己总结学习,亦供网友参考。

2.问题汇总

问题一:
不好意思,我有事,先处理一下,你先写个非递归二分查找。
答:
这个和上次CVTE面试的第一个问题相同,之前复习过。感觉很多面试的第一个问题都是先写段代码。因此,手写代码感觉很重要,因为这是给面试官的第一印象。除了二分查找,快排,链表反转,实现atoi()函数等等,在面试中也常被用来作为手写代码的考题。

//数组递增有序 int binarySearch(int* array,int len,int value){ int mid=0; int low=0; int high=len-1; while(low<=high){        mid=(low+high)/2; if(array[mid]==value) //找到 return mid; if(value>array[mid]) //在右半区 low=mid+1; else //在左半区 high=mid-1;         } return -1; //查找失败 }<ul class="pre-numbering" style="box-sizing:border-box;position:absolute;width:50px;top:0px;left:0px;margin:0px;padding:6px 0px 40px;border-right-width:1px;border-right-style:solid;border-right-color:#DDDDDD;list-style:none;text-align:right;background-color:#EEEEEE;"><li style="box-sizing:border-box;padding:0px 5px;">1</li><li style="box-sizing:border-box;padding:0px 5px;">2</li><li style="box-sizing:border-box;padding:0px 5px;">3</li><li style="box-sizing:border-box;padding:0px 5px;">4</li><li style="box-sizing:border-box;padding:0px 5px;">5</li><li style="box-sizing:border-box;padding:0px 5px;">6</li><li style="box-sizing:border-box;padding:0px 5px;">7</li><li style="box-sizing:border-box;padding:0px 5px;">8</li><li style="box-sizing:border-box;padding:0px 5px;">9</li><li style="box-sizing:border-box;padding:0px 5px;">10</li><li style="box-sizing:border-box;padding:0px 5px;">11</li><li style="box-sizing:border-box;padding:0px 5px;">12</li><li style="box-sizing:border-box;padding:0px 5px;">13</li><li style="box-sizing:border-box;padding:0px 5px;">14</li><li style="box-sizing:border-box;padding:0px 5px;">15</li><li style="box-sizing:border-box;padding:0px 5px;">16</li></ul>

问题二:
(面试官一直在打电话)如果你写完了,你再写一个从数组中找出第二大的数。
答:
找第几大的数突然间想到了堆排序,因为自己之前练习过堆排序,所以就花了十分钟左右的时间写下了堆排序。写堆排序需要知道节点下标index的左子节点的下标为2*index+1,2*index+2。以数组构造堆的话是一个完全二叉树,数组长度为len,那么最后一个非叶子节点的下标是len/2-1。以堆排序来寻找第二大数参考代码如下:

//手写大顶堆排序求大二大数 void adjust(int A[],int index,int len){ if(index>len/2-1)//叶子节点,不同调整 return; int biggestIndex=0; if(2*index+2<len)        biggestIndex=A[2*index+1]>A[2*index+2]?2*index+1:2*index+2; else biggestIndex=2*index+1; if(A[index]index]=A[index]+A[biggestIndex];        A[biggestIndex]=A[index]-A[biggestIndex];        A[index]=A[index]-A[biggestIndex];        adjust(A,biggestIndex,len);    }} void createMaxHeap(int A[],int len){ for(int i=len/2-1;i>=0;--i){        adjust(A,i,len);    }   } int getSecondMax(int A[],int len){    createMaxHeap(A,len); //建堆 for(int i=0;i<2;++i){        A[0]=A[0]+A[len-1-i];        A[len-1-i]=A[0]-A[len-1-i];        A[0]=A[0]-A[len-1-i];        adjust(A,0,len-1-i);    } return A[len-2];}<ul class="pre-numbering" style="box-sizing:border-box;position:absolute;width:50px;top:0px;left:0px;margin:0px;padding:6px 0px 40px;border-right-width:1px;border-right-style:solid;border-right-color:#DDDDDD;list-style:none;text-align:right;background-color:#EEEEEE;"><li style="box-sizing:border-box;padding:0px 5px;">1</li><li style="box-sizing:border-box;padding:0px 5px;">2</li><li style="box-sizing:border-box;padding:0px 5px;">3</li><li style="box-sizing:border-box;padding:0px 5px;">4</li><li style="box-sizing:border-box;padding:0px 5px;">5</li><li style="box-sizing:border-box;padding:0px 5px;">6</li><li style="box-sizing:border-box;padding:0px 5px;">7</li><li style="box-sizing:border-box;padding:0px 5px;">8</li><li style="box-sizing:border-box;padding:0px 5px;">9</li><li style="box-sizing:border-box;padding:0px 5px;">10</li><li style="box-sizing:border-box;padding:0px 5px;">11</li><li style="box-sizing:border-box;padding:0px 5px;">12</li><li style="box-sizing:border-box;padding:0px 5px;">13</li><li style="box-sizing:border-box;padding:0px 5px;">14</li><li style="box-sizing:border-box;padding:0px 5px;">15</li><li style="box-sizing:border-box;padding:0px 5px;">16</li><li style="box-sizing:border-box;padding:0px 5px;">17</li><li style="box-sizing:border-box;padding:0px 5px;">18</li><li style="box-sizing:border-box;padding:0px 5px;">19</li><li style="box-sizing:border-box;padding:0px 5px;">20</li><li style="box-sizing:border-box;padding:0px 5px;">21</li><li style="box-sizing:border-box;padding:0px 5px;">22</li><li style="box-sizing:border-box;padding:0px 5px;">23</li><li style="box-sizing:border-box;padding:0px 5px;">24</li><li style="box-sizing:border-box;padding:0px 5px;">25</li><li style="box-sizing:border-box;padding:0px 5px;">26</li><li style="box-sizing:border-box;padding:0px 5px;">27</li><li style="box-sizing:border-box;padding:0px 5px;">28</li><li style="box-sizing:border-box;padding:0px 5px;">29</li><li style="box-sizing:border-box;padding:0px 5px;">30</li><li style="box-sizing:border-box;padding:0px 5px;">31</li><li style="box-sizing:border-box;padding:0px 5px;">32</li><li style="box-sizing:border-box;padding:0px 5px;">33</li><li style="box-sizing:border-box;padding:0px 5px;">34</li><li style="box-sizing:border-box;padding:0px 5px;">35</li><li style="box-sizing:border-box;padding:0px 5px;">36</li></ul>

很显然,这个求解方法的时间复杂度是nlogn,不是较优解法,不是面试官想要的答案。面试官追问有没有更好的方法,时间复杂度是O(n)。

稍微想了一下,回答冒泡排序和简单选择排序可以在O(2n)的时间复杂度找到第二大的数。他试官说还有没有更快的方法呢?不要O(2n),只要O(n)。

正确答案是:
保存最大值和第二大值,扫描一遍数组即可找到,也就是以空间换时间。冒泡排序和简单选择排序都需要扫描两遍。参考如下代码:

int getSecondMax(int array[],int len){ if(len<=1) return -1; int max=0,secondMax=0; if(array[0]>array[1]){        max=array[0];        secondMax=array[1];    }else{        max=array[1];        secondMax=array[0];    } for(int i=2;i<len;++i){ if(array[i]<secondMax) continue; if(array[i]<max&&array[i]>secondMax) //新的第二大数 secondMax=array[i]; else max=array[i]; //最大数 } return secondMax;}<ul class="pre-numbering" style="box-sizing:border-box;position:absolute;width:50px;top:0px;left:0px;margin:0px;padding:6px 0px 40px;border-right-width:1px;border-right-style:solid;border-right-color:#DDDDDD;list-style:none;text-align:right;background-color:#EEEEEE;"><li style="box-sizing:border-box;padding:0px 5px;">1</li><li style="box-sizing:border-box;padding:0px 5px;">2</li><li style="box-sizing:border-box;padding:0px 5px;">3</li><li style="box-sizing:border-box;padding:0px 5px;">4</li><li style="box-sizing:border-box;padding:0px 5px;">5</li><li style="box-sizing:border-box;padding:0px 5px;">6</li><li style="box-sizing:border-box;padding:0px 5px;">7</li><li style="box-sizing:border-box;padding:0px 5px;">8</li><li style="box-sizing:border-box;padding:0px 5px;">9</li><li style="box-sizing:border-box;padding:0px 5px;">10</li><li style="box-sizing:border-box;padding:0px 5px;">11</li><li style="box-sizing:border-box;padding:0px 5px;">12</li><li style="box-sizing:border-box;padding:0px 5px;">13</li><li style="box-sizing:border-box;padding:0px 5px;">14</li><li style="box-sizing:border-box;padding:0px 5px;">15</li><li style="box-sizing:border-box;padding:0px 5px;">16</li><li style="box-sizing:border-box;padding:0px 5px;">17</li><li style="box-sizing:border-box;padding:0px 5px;">18</li><li style="box-sizing:border-box;padding:0px 5px;">19</li><li style="box-sizing:border-box;padding:0px 5px;">20</li><li style="box-sizing:border-box;padding:0px 5px;">21</li></ul>

问题三:
C++中struct和class的区别?
答:
(1)关于继承和访问权限,struct默认的继承访问权限为public,class为private;
(2)关于大括号初始化,C++中的struct是对C中的struct的扩充,同时兼容C中struct应有的大括号初始化特性。
class和struct如果定义了构造函数的话,都不能用大括号进行初始化;
如果没有定义构造函数,struct可以用大括号初始化;
如果没有定义构造函数,且所有成员变量全是public的话,可以用大括号初始化。

事实上,这个区别是由上面的区别造成的,所以这个可以不算一个区别。
(3)关于模版,在模版中,类型参数前面可以使用class或typename,不能使用struct。

问题四:
说说C++多态的实现机制。
答:
简单来说,就是通过虚函数表来实现的,具体请参考:CVTE面试问题汇总.

问题五:
C中static关键字的作用。
答:
(1)修饰变量,一是表名变量存储空间在全局静态存储区,二是变量生命周期是真个程序的生命周期,三是变量作用域限定在当前文件。

(2)修饰函数,限制函数的作用域为当前文件。

问题五:
C中extern关键字的作用。
答:
extern修饰变量和函数起到声明的作用,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他文件中寻找其定义。

问题六:
C++中extern "C"的作用。
答:
C++中extern "C"修饰函数时,指明该函数以C的方式进行编译和链接。具体来说就是C++函数支持函数重载,C不支持函数重载,原因二者的函数签名不同。

如函数void foo(int,int)被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为”mangledname”)。

问题七:
说一下CC++程序的内存布局。
答:
目前我还没有找到很权威的著作对此问题有详细的论述,肯定有,只是我还不知道。看了《C++高级进阶教程》中描述如下。

如果内存地址由下到上的是从低地址到高地址,那么程序的内存布局大致如下:
这里写图片描述

问题七:
僵尸进程是如何产生的。
答:
在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他, 那么他将变成一个僵尸进程。

问题八:
僵尸进程如何避免。
答:
(1)父进程通过wait和waitpid等函数等待子进程结束,但这会导致父进程挂起。
(2)如果父进程很忙,那么可以用signal函数为SIGCHLD安装handler,因为子进程结束后, 父进程会收到该信号,可以在handler中调用wait回收。
(3)如果父进程不关心子进程什么时候结束,那么可以用signal(SIGCHLD,SIG_IGN)通知内核,自己对子进程的结束不感兴趣,那么子进程结束后,内核会回收, 并不再给父进程发送信号。
(4)还有一些技巧,就是fork两次,父进程fork一个子进程,然后继续工作,子进程fork一 个孙进程后退出,那么孙进程被init接管,孙进程结束后,init会回收。不过子进程的回收 还要自己做。

问题九:
写一个宏,给定数组名求数组长度,数组类型未知。
答:
想到sizeof就可以很容易求出来了。思路是先用sizeof(array)求出数组占用的内存空间大小(单位字节),再通过sizeof求出数组单个元素的类型大小(单位字节),前者除以后者即可。

#define func(array) sizeof(array)/sizeof(array[0])<ul class="pre-numbering" style="box-sizing:border-box;position:absolute;width:50px;top:0px;left:0px;margin:0px;padding:6px 0px 40px;border-right-width:1px;border-right-style:solid;border-right-color:#DDDDDD;list-style:none;text-align:right;background-color:#EEEEEE;"><li style="box-sizing:border-box;padding:0px 5px;">1</li></ul>

问题十:
Linux下awk和sed了解过吧,给定一个文本文件,编写shell脚本将文件中重复的行删除。
答:
使用sort+uniq/awk/sed可以来完成。
方法一:利用sort以不重复的方式打印出文件所有的行并排序-u,表示unique。

sort -u file<ul class="pre-numbering" style="box-sizing:border-box;position:absolute;width:50px;top:0px;left:0px;margin:0px;padding:6px 0px 40px;border-right-width:1px;border-right-style:solid;border-right-color:#DDDDDD;list-style:none;text-align:right;background-color:#EEEEEE;"><li style="box-sizing:border-box;padding:0px 5px;">1</li></ul>

方法二:利用sort先对文件按行排好序之后再交由uniq处理。sort -k 指定列,-t指定列分隔符。

sort -k 1 -t ':' file|uniq<ul class="pre-numbering" style="box-sizing:border-box;position:absolute;width:50px;top:0px;left:0px;margin:0px;padding:6px 0px 40px;border-right-width:1px;border-right-style:solid;border-right-color:#DDDDDD;list-style:none;text-align:right;background-color:#EEEEEE;"><li style="box-sizing:border-box;padding:0px 5px;">1</li></ul>

方法三:利用sort+awk来完成。

sort file | awk '{if ($0!=line) print;line=$0}'<ul class="pre-numbering" style="box-sizing:border-box;position:absolute;width:50px;top:0px;left:0px;margin:0px;padding:6px 0px 40px;border-right-width:1px;border-right-style:solid;border-right-color:#DDDDDD;list-style:none;text-align:right;background-color:#EEEEEE;"><li style="box-sizing:border-box;padding:0px 5px;">1</li></ul>

if ($0!=line) print;表示当前行是否等于上一行,不等于的话则打印,line开始是空的。line=$0表示当前行赋给line。

方法四:利用sort+sed来完成。

sort file | sed '$!N; /^\(.*\)\n\1$/!P;D'<ul class="pre-numbering" style="box-sizing:border-box;position:absolute;width:50px;top:0px;left:0px;margin:0px;padding:6px 0px 40px;border-right-width:1px;border-right-style:solid;border-right-color:#DDDDDD;list-style:none;text-align:right;background-color:#EEEEEE;"><li style="box-sizing:border-box;padding:0px 5px;">1</li></ul>

稍后解释。

问题十一:
有用过Linux中的epoll吗?它的作用是什么?
答:
epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。

问题十二:
epoll和select的区别在哪,或者说优势在哪?
答:
(1)epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered);
(2)select的句柄数目受限,在linux/posix_types.h头文件有这样的声明:#define __FD_SETSIZE 1024,表示select最多同时监听1024个fd。而epoll没有,epoll的最大并发的连接数的理论值无上限,但由于实际内存资源有限,实际并发的连接数受到资源的限制和最大的打开文件句柄数目的限制;
(3)epoll的最大好处是不会随着FD的数目增长而降低效率,在selec中采用轮询处理,其中的数据结构类似一个数组的数据结构,而epoll 是维护一个队列,直接看队列是不是空就可以了。
(4)使用mmap加速内核与用户空间的消息传递。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。

此外,epoll创建时传入的参数是什么?
创建一个epoll的实例,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

问题十三:
给定数据表table1如下,编写SQL语句找出出现次数前三的年龄。
这里写图片描述
答:
在MS Access中测试跑通,参考语句如下:

select top 3 table2.Age,table2.num from (select Age,count(Age) as num from table1 group by Age) as table2 Order By table2.num DESC<ul class="pre-numbering" style="box-sizing:border-box;position:absolute;width:50px;top:0px;left:0px;margin:0px;padding:6px 0px 40px;border-right-width:1px;border-right-style:solid;border-right-color:#DDDDDD;list-style:none;text-align:right;background-color:#EEEEEE;"><li style="box-sizing:border-box;padding:0px 5px;">1</li></ul>

问题十四:
网络的五层协议模型。
答:
很简单,如下图所示:
这里写图片描述

问题十五:
咱们聊一下架构的事情。如果你现在是一位架构师,如何实现QQ的大量用户并发登陆,应该考虑哪些问题?又该如何解决?
答:
(1)传输协议选择。
(2)负载均衡。
(3)线程和进程的选择,以及优化。

问题十六:
你了解过数据挖掘吗。对这方面感兴趣吗?

答:
没了解过但很感兴趣。

问题十七:
你还有什么问题要问的。

答:
请问您搞安全技术方面需要对数据库和SQL掌握很精通吗?
面试官:无需精通,但是要有良好的基础,常用的SQL要会写。

3.小结

面试官也是比较温和的人,很有耐心,整个过程节奏也很缓慢。不会的问题尽量去思考,面试官希望看到面试者的思考过程,不懂的我也向他请教,寻求提示,这也间接的产生了互动。

整个面试过程所遇到的问题,除了最后一个是比较开发的题目,前面都是比较基础的题目。之所以问这些问题,还是就个人简历中提到的求职技能和相关项目进行相关问题提问。在SQL和shell脚本方面,因为很多年没写SQL了,所以基本忘记,shell脚本,尽管平时在Linux环境编程,但是很少写,写的话也是参考网上资源,一时无任何参考手写确实有些不适,看来SQL和shell这方面要加强了。


www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1119678.htmlTechArticle腾讯C++后台招聘问题汇总与分享 1.前言 2016.4.11日广州天河区东圃喜来登酒店参加了Tencent CC++后台技术一面,面试官人很温和,经历了大概...
陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
超越炒作:評估當今PHP的角色超越炒作:評估當今PHP的角色Apr 12, 2025 am 12:17 AM

PHP在現代編程中仍然是一個強大且廣泛使用的工具,尤其在web開發領域。 1)PHP易用且與數據庫集成無縫,是許多開發者的首選。 2)它支持動態內容生成和麵向對象編程,適合快速創建和維護網站。 3)PHP的性能可以通過緩存和優化數據庫查詢來提升,其廣泛的社區和豐富生態系統使其在當今技術棧中仍具重要地位。

PHP中的弱參考是什麼?什麼時候有用?PHP中的弱參考是什麼?什麼時候有用?Apr 12, 2025 am 12:13 AM

在PHP中,弱引用是通過WeakReference類實現的,不會阻止垃圾回收器回收對象。弱引用適用於緩存系統和事件監聽器等場景,需注意其不能保證對象存活,且垃圾回收可能延遲。

解釋PHP中的__ Invoke Magic方法。解釋PHP中的__ Invoke Magic方法。Apr 12, 2025 am 12:07 AM

\_\_invoke方法允許對象像函數一樣被調用。 1.定義\_\_invoke方法使對象可被調用。 2.使用$obj(...)語法時,PHP會執行\_\_invoke方法。 3.適用於日誌記錄和計算器等場景,提高代碼靈活性和可讀性。

解釋PHP 8.1中的纖維以進行並發。解釋PHP 8.1中的纖維以進行並發。Apr 12, 2025 am 12:05 AM

Fibers在PHP8.1中引入,提升了並發處理能力。 1)Fibers是一種輕量級的並發模型,類似於協程。 2)它們允許開發者手動控制任務的執行流,適合處理I/O密集型任務。 3)使用Fibers可以編寫更高效、響應性更強的代碼。

PHP社區:資源,支持和發展PHP社區:資源,支持和發展Apr 12, 2025 am 12:04 AM

PHP社區提供了豐富的資源和支持,幫助開發者成長。 1)資源包括官方文檔、教程、博客和開源項目如Laravel和Symfony。 2)支持可以通過StackOverflow、Reddit和Slack頻道獲得。 3)開發動態可以通過關注RFC了解。 4)融入社區可以通過積極參與、貢獻代碼和學習分享來實現。

PHP與Python:了解差異PHP與Python:了解差異Apr 11, 2025 am 12:15 AM

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

php:死亡還是簡單地適應?php:死亡還是簡單地適應?Apr 11, 2025 am 12:13 AM

PHP不是在消亡,而是在不斷適應和進化。 1)PHP從1994年起經歷多次版本迭代,適應新技術趨勢。 2)目前廣泛應用於電子商務、內容管理系統等領域。 3)PHP8引入JIT編譯器等功能,提升性能和現代化。 4)使用OPcache和遵循PSR-12標準可優化性能和代碼質量。

PHP的未來:改編和創新PHP的未來:改編和創新Apr 11, 2025 am 12:01 AM

PHP的未來將通過適應新技術趨勢和引入創新特性來實現:1)適應云計算、容器化和微服務架構,支持Docker和Kubernetes;2)引入JIT編譯器和枚舉類型,提升性能和數據處理效率;3)持續優化性能和推廣最佳實踐。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境