在这里给大家整顿了腾讯、阿里、百度、华为、头条等一共九家大厂2020年的面试题以及答案,篇幅所限,我就每家的只放两道题了,有须要完整版的敌人能够评论区留言获取。不足我的项目实战经验的小老弟能够点这里☞c/c++企业级我的项目实战。

文末还给大家放了一份学习纲要,如果看完文章能棘手给我点个赞那就再好不过了。

一、腾讯

1.删除字符串s1中在字符串s2中呈现的字符。

基本思路:把s1的字符存到一个set外面,而后遍历s2,看是否呈现过,呈现过就erase掉。然而间接输入set的元素这样会扭转程序,要想程序不变,就程序遍历一下s1 看是否呈现,呈现就输入。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <vector>#include <set>#include <queue>#include <map>using namespace std;typedef long long LL;const int maxn=1005;set<char>s;int main() {string s1,s2;cin>>s1>>s2;int len=s1.length();for (int i=0;i<len;i++)s.insert(s1[i]);len=s2.length();for (int i=0;i<len;i++){if (s.count(s2[i]))s.erase(s.find(s2[i]));}len=s1.length();for (int i=0;i<len;i++){if (s.count(s1[i]))cout<<s1[i];}cout<<endl;return 0;

2. 求一个论坛的在线人数,假如有一个论坛,其注册ID有两亿个,每个ID从登陆到退出会向一个日志文件中记下登陆工夫和退出工夫,要求写一个算法统计一天中论坛的用户在线散布,取样粒度为秒。

答案:

一天总共有3600*24=86400秒。

定义一个长度为86400的整数数组intdelta[86400],每个整数对应这一秒的人数变动值,可能为正也可能为负。开始时将数组元素都初始化为0。

而后顺次读入每个用户的登录工夫和退出工夫,将与登录工夫对应的整数值加1,将与退出工夫对应的整数值减1。

这样解决一遍后数组中存储了每秒中的人数变动状况。

定义另外一个长度为86400的整数数组intonline_num[86400],每个整数对应这一秒的论坛在线人数。

假如一天开始时论坛在线人数为0,则第1秒的人数online_num[0]=delta[0]。第n+1秒的人数online_num[n]=online_num[n-1]+delta[n]。

这样咱们就取得了一天中任意工夫的在线人数。

二、阿里巴巴

1、应用mysql索引都有哪些准则?索引什么数据结构? B+tree和B tree什么区别?

答案:

1、    对于查问频率高的字段创立索引;

2、    对排序、分组、联结查问频率高的字段创立索引;

3、    索引的数目不宜太多 起因:a、每创立一个索引都会占用相应的物理控件; b、过多的索引会导致insert, update、delete语句的执行效率升高;

4、    若在理论中,须要将多个列设置索引时,能够采纳多列索引 如:某个表(假如表名为Student),存在多个字段(StudentNo, StudentName, Sex, Address, Phone, BirthDate),其中须要71 StudentNo, StudentName 字段进行查问,对 Sex字段进行分组,对BirthDate字段逹行排序,此时能够创立多列索引index index_najne (StudentNo, StudentName, Sex, BirthDate) ;#index_najne 为索引名 在下面的语句中只创立了一个索引,然而对4个字段都赋予了豪引的性能。 创立多列索引,须要遵循BTree类型,即第一列应用时,才启用索引。 在下面的创立语句中,只有mysql语句在应用到StudentNo字段时,索引才会被启 用。 如: select from Student wheie StudentNo = 1000; #应用到了 StudentNo 字段,索引被启用。 以应用explain检测索引是否被启用如:explain select from Student where StudentNo = 1000;

5、    抉择唯一性索引 唯一性索引的值是惟一的,能够更疾速的通过该索引来确定某条记录。例如,学生 表中学号是具备唯一性的字段。为该字段建设唯一性索引能够很快的确定某个学生的 信息。如果应用姓名的话,可能存    在同名景象,从而升高查问速度。

6、    尽量应用数据量少的索引 如果索引的值很长,那么查问的速度会受到影响。例如,对一个CHAR (100)类型的 字段进行全文检索    须要的工夫必定要比对CHAR (10)类型的字段 须要的工夫要多。

7、    尽量应用前缀来索引 如果索引字段的值很长,最好应用催的前缀来索引。例如,TEXT和BLOG类型的字 段,进行全文检索会很浪费时间。如果只检索字段的后面的若干个字符,这样能够提 高检索速度。

8、    删除不再应用或者很少应用的索引. 表中的数据被大量更新,或者数据的应用形式被扭转后,原有的一些索引可能不再 须要。数据库管理员该当定期找出这些索引,将它们删除,从而缩小索引对更新操作 的影响B+ tree树索引,B tree,散列

2、Mysql有哪些存储引擎?请具体列举其区别?

答案:

InnoDB:事务型存储引擎,并且有较高的并发读取频率

MEMORY:存储引擎,寄存在内存中,数据量小,速度快

Merge: ARCHIVE:归档,有很好的压缩机制

3、设计高并发零碎数据库层面该如何设计?数据库锁有哪 些类型?如何实现?

答案:

分库分表:同样量的数据均匀存储在不同数据库雷同表(或不同表)中,加重单表 压力,如果还是很大,就能够每个库在分多张表,依据hash取值或者其余逻辑判断将 数据存储在哪张表中

读写拆散:数据库本来就有主从数据库之分,查问在从服务器,増删改在主服务器,

归档和操作表辨别:建一张归档表,将历史数据放入,须要操作的表数据独自存储

索引之类的创立,对于数据量很大,百万级别以上的单表,如果増删改操作不频 繁的话,能够创立bitMap索引,速度要快得多

       共享锁:要等第一个人操作完,开释锁,能力操作

       更新锁:解决死锁,他人能够读,但不能操作

       排他锁:读写都被禁用

       意向锁(xlock):对表中局部数据加锁,查问时,能够跳过

       打算锁:操作时,别的表连贯不了这张表

三、百度

1、输出www.baidu.com在浏览器的残缺过程,越具体越好。

答案:

浏览器获取输出的域名ww. baidu. com

浏览器向域名零碎

DNS申请解析ww. baidu. com的IP地址 DNS解析出百度服务器的IP地址

浏览器与服务器建设TCP连贯(默认端口 80)

浏览器收回HTTP申请,申请百度首页

服务器通过HTTP申请把首页文件发给浏览器

TCP连贯开释

浏览器解析首页文件,展现web界面

2、请形容C/C++程序的内存分区?

答案:

其实c和c卄的内存分区还是有肯定区别的,但此处不作辨别:

1)    、栈区(stack)-由编译器主动调配軽放,寄存函数的参数值,局部变量的值等。 其 操作形式相似于数据结构中的栈。

2)    、堆区(heap) ——般由程序员调配开释,若程序员不軽放,程序完结时可能由 OS回 收。留神它与数据结构中的堆是两回事,调配形式倒是相似于链表。

3)    、全局区(动态区)(static) —,全局变量和动态变量的存储是放在一块的,初 始化的 全局变量和动态变量在一块区域,未初始化的全局变量和未初始化的动态变量在相邻 的另 —块区域。-程序完结后由零碎开释。

4)    、文字常量区一常量字符串就是放在这里的。程序完结后由零碎开释。

5)    、程序代码区一寄存函数体的二进制代码。 栈区与堆区的区别:

    1)    堆和栈中的存储内容:栈存局部变量•,函数参数等。堆存储应用new、malloc申请 的变量等;

    2)    申请形式:栈内存由零碎调配,堆内有由本人申请;

    3)    申请后零碎的响应:栈一一只有栈的残余空间大于所申请空间,零碎将为程序提供 内存,否则将报异样提醒栈溢出。 堆一一首先应该晓得操作系统有一个记录闲暇内存地址的链表,当零碎收到程序的申请 时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,而后将该结点从闲暇结 点链表中删除,并将该结点的空间调配蜘程序; 申请大小的限度:WindowsT栈的大小个别是2M,堆的容量较大; 申请效率的比拟:栈由零碎主动调配,速度较快。堆应用new、malloc等调配,较 慢;

总结:

栈区劣势在解决效率,堆区劣势在于灵便;

内存模型:自由区、动态区、动静区;

依据c/c++对象生命周期不同,c/c++的内存模型有三种不同的内存区域,即:自在存 储区,动静区、动态区。 自在存储区:

部分非动态变量的存储区域,即平时所说的栈; 动静区:用new , malloc调配的内存,即平时所说的堆;

靜态区:全局变量,动态变量,字符串常量存在的地位; 注:代码尽管占内存,但不属于c/c卄内存模型的一部分;

四、华为

1、static有什么用处?(请至多阐明两种)

答案:

1)    在函数体,一个被申明为动态的变量在这一函数被调用过程中維持其值 不变。

2)    在模块内(但在函数体外),一个被申明为动态的变量能够被模块内所 用函数拜访,但不能被模块外其它函数拜访。它是一个本地的全局变量。

3)    在模块内,一个被申明为动态的函数只可被这一模块内的其它函数调用。 那就是,这个函数被限度在申明它的模块的本地范畴内应用

2、援用与指针有什么区别?

答案:

1)    援用必须被初始化,指针不用。

2)    援用初始化当前不能被扭转,指针能够扭转所指的对象。

3)    不存在指向空值的援用,然而存在指向空值的指针。

3、某32位零碎下,C++程序,请计算sizeof的值.

char str[] = rthttp: //www. ibegroi5>. com/wchar *p = str ;int n = 10;sizeof (str ) = ? (1)sizeof ( p ) = ? (2)sizeof ( n ) = ? (3) void Foo ( char str [100]) (mmsizeof( str ) = ?(4)}void *p = malloc( 100 );mmsizeof ( p ) = ? (5)17 (2) 4 (3) 4 (4) 4 (5) 4 

五、京东

1、求此N的最小公倍数。把每个数字合成质因数,算他们 每个质因数的奉献,而后乘起来。

#include<bits/stdc++. h>using namespace std;typedef long long 11;#define maxn 100009int fact [maxn];bool prime [maxn];11 mod = 987654321;int cal (int t, int p) {int ent = 0;while(t % p == 0) { cnt++;t /= P;return ent;void first () {memset (prime, true, sizeof (prime)); prime[1] = false;for(int i = 2; i <= 100000; i++: { int top = sqrt(i);for(int j = 2; j <= top; j—) { if(i % j == 0){ prime[i] = false; break;void solve(int Limit) { first ();for (int i = 2; i <= Limit; i++' { int top = sqrt(i);for (int j = 2; j <= top; ji) { if(prime[j] && i % j == 0) {fact[j] = max (fact [j], cal (i, j));Iif(prime[i])fact [i] = max (fact [i], 1);}}int main() {11 n;cin^^n;solve (n);11 ans = 1;for(11 i = 1; i <= n; i++) {for (11 j = 1; j <= fact[i]; j++) {ans = ans * i % mod;}}cout<<ai^s<<endl;return 0; 

2、去掉字符串形成回文。其实是经典的求回文子序列个数。

# inc lude <b i t s /s t dc++. h>using namespace std;typedef long long 11;11 f[59] [59];string str;11 dfs(int i, int j) {i£(i > j) {return 0;}if(i == j) {f[i] [j] = 1;return f [i] [j];}[j] != 0){return f [i] [j];f [i] [j] = dfs (i, j - 1) + dfs(i + 1, j) - dfs(i + 1, j - 1); if (str [i] == str[j])f [i] [j] += dfs(i + 1, j - 1: + 1;return f [i] [j];int main。{cin>>sh;int len = str.length();cout«dfs(0, len - l)«endl;return 0; 

六、美团

1、已知一个函数rand7()可能生成1-7的随机数,请给岀一个 函数,该函数可能生成1-10的随机数。

该解法基于一种叫做回绝采样的办法。次要思维是只有产生一个指标范畴内的随机数, 则间接返回。如果产生的随机数不在指标范畴内,则抛弃该值,从新取样。因为指标范 围内的数字被选中的概率相等,这样一个平均的散布生成了。显然rand7至多须要执行2次,否则产生不了 1T0的数字。通过运行:rand7两次,可 以生成1-49的整数,2 3 4 5 6 71 2 3 4 5 6 78 9 10 1 2 3 45 6 7 8 9 10 12 3 4 5 6 7 89 10 1 2 3 4 56 7 8 9 10 * ********因为49不是10的倍数,所以咱们须要抛弃一些值,咱们想要的数字范畴为1-40,不 在此范畴则抛弃并从新取样。代码:int randlOO {int row, col, idx;do {row = randT ();col = randT ();idx = col + (row-1) *7;} while (idx > 40);return 1 + (idx-l)%10;}因为row范畴为1-7, col.范畴为1-7,这样idx值范畴为1-49。大于40的值被抛弃, 这样剩下1-40范畴内的数字,通过取模返回。上面计算一下失去一个满足1-40范畴的 数须要进行取样的次数的期望值:E(# calls to rand7) = 2 * (40/49) +4 * (9/49) » (40/49) +6 * (9/49)2 * (40/49) +8=$ 2k * (9/49)k_1 » (40/49) k=l=(80/49) / (1 - 9/49)2=2.45 

2、C++11创立线程的三种形式

通过暨!thread:规范库的类join:阻塞主线程并期待// MultiThread, cpp : Defines the en~ry point for the console application.#include 〃stdafx・h〃#include^iostream>#include<vec t or >#include<map>#include<string>it inc lude < thr e ad>using namespace std;void myPrint()[cout « "线程幵始运行”« endl;cout « 〃线程运行完结了” « end*std:: thread my20bj (myPrint); // 可调用对象 my20bj. joint);//主线程阻塞在这.,并期待myPrint()执行完 cout « ^wangtao^ « endl;return 0;detachO:将主线程和子线程齐全拆散,子线程会驻留在后盾运行,被CH运行时库接 管,失去管制joinable ():判断是否能够胜利应用join。或者detach()程序阐明:detach后不能在施行join std: : thread my20bj (myPrint); //主线程阻塞在这,并期待myPrint ()执行完 if (my20bj. joinable ()) {cout « ^1: joinable () == hue" « endl;}else {cout « ^1:joinable() == false” « endl;}my20bj. detachO ;if (my20bj. j oinable()) {cout « "2: joinable () == hue" « endl;}else {cout « °2:joinable() == false” « endl;Icout«〃祁angtaol”«endl;cout«〃祁angtao2"«endl;cout«〃祁angtao3”«endl;cout«〃祁angtao4〃«endl;cout«〃祁angtao5”«endl;cout«〃祁angtao6〃«endl;cout«^wangtao?^«endl;cout«〃祁angtao8〃«endl;Ireturn 0;intmain0std:: thread my20bj (myPrint); //主线程阻塞在这,并期待myPrint ()执行完 if (my20bj. joinable ()) {my20bj. join();cout«〃祁angtaol”«endl;cout«〃祁angtao2"«endl;cout«〃祁angtao3”«endl;cout<<〃wangtao4〃<<endl;cout«〃祁angtao5”«endl;cout«〃祁angtao6〃«endl;cout«^wangtao?^«endl;cout«〃祁angtao8〃«endl;return 0;通过类对象创立线程class CObject[public:void operator () () {cout « "线程幵始运行"« endl; cout « '线程完结运行〃 « endl;int main()[CObject obj;std:: thread my20bj (obj); //主线程阻塞在这,并期待myPrint ()执行完 if (my20bj. joinable ()) {my20bj. join();}cout « see you << endl;return 0;class CObject[int& m_obj;public:CObject(int& i) :m_obj(i) {} void operator () () { // 不带参数 cout « "线程幵始运行1” « endl; cout « "线程幵始运行2” « endl; cout « "线程幵始运行3" « endl; cout « "线程幵始运行4” « endl; cout « "线程幵始运行5” « endl;int main。[int i = 6;CObject obj (i);std:: thread my20bj (obj); //主线程阻塞在这,并期待myPrint ()执行完 if (my20bj. joinable ()) {my20bj. detachO ;cout « "sue you " « endl;return 0;用detach ()主线程完结对象即被销毁,那么子线程的成员函数还能调用吗?这里的的对象会被复制到子线程中,当主线程完结,复制的子线程对象并不会被销毁 只有是没有援用、指针就不会呈现问题通过复制构造函数和析构函数来燈证对象是否复制到了子线程中// MultiThread. cpp : Defines the eniry point for the console application.//#include "stdafx.h”#include<iostreajn>#include<vector>Ji include〈map >#include<string>#include<thread>using namespace std;class CObject[int& m_obj;public:CObject(int& i) :m_obj(i) {cout « "ctor” « endl;}CObject(const CObject& m) :m_obj(m.m_obj) {cout « "copy ctor" « endl.}"CObject() {cout « "dtor” « endl;Ivoid operator () () { // 不带参数cout « "线程幵始运行1” « endl;cout « "线程幵始运行2” « endl;cout « "线程幵始运行3" « endl;cout « "线程幵始运行4” « endl;cout « "线程幵始运行5” « endl;int main。[int i = 6;CObject obj (i);std:: thread my20bj (obj); //主线程阻塞在这,并期待myPrint ()执行完 if (my20bj. joinable ()) {my20bj. detachO ;}cout << see you << endl;return 0;子线程的析构函数在后盾执行,所以输入的dt皿是主线程的。用join()后果为:通过lambda表达式创立线程int main。[auto myLamThread = [] {cout « "线程幵始运行"« endl;cout « '线程完结运行”« endl;};thread cthread(myLamThread);cthread. joint);std::cout « 〃see you " « endl.return 0; 

七、头条

1、C++智能指针如何解决内存泄露问题

`shazedjtr共享的智能指针std::shmed_ph应用援用计数,每一个sharedjtr的拷贝都指向雷同的内存。在最 后一个shared_ptr析构的时候,内存才会被开释。能够通过构造函数、std_make_shared辅助函数和reset办法来初始化shared_ptr://构造函数初始化std::shared_ptrp ( new int(1));std::shared_ptrp2 = p ;//对于一个未初始化的智能指针,能够通过reset办法来初始化。std::shared_ptrptr; ptr.reset ( new int (1));if (ptr) {cout « "ph is not null.n^ ; }不能将一个原始指针间接赋值给一个智能指针:std: : shared_ptrp = new int(l) ;//编译报错,不容许间接赋值获取原始指针:通过get办法来返回原始指针std::shared_ptrptr ( new int(1));int * p =ptr. get ();指针删除器:智能指针初始化能够指定删除器void DeletelntPtr ( int * p ) {delete p ;}std::shared_ptrp ( new int , DeletelntPtr );当P的援用技术为o时,主动调用删除器来开释对象的内存。删除器也能够是一个 lambda表达式,例如std::shared_ptrp ( new int , [](int * p){delete p});注意事项:.不要用一个原始指针初始化多个shared_ptro.不要再函数实参中创立Shared_ptr,在调用函数之前先定义以及初始化它。(。).不荽将lhi»指针作为 ^Cd_plx返回进去。0).要防止循环援用。unique_ptr独占的智能指针unique_ptr是一个独占的智能指针,他不容许其余的智能指针共享其外部的指针,不 容许通过赋值将一个unique_ptr赋值给另外一个unique_ptrounique_ptr不容许复制,但能够通过函数返回给其余的unique_ptr,还能够通过 std::move来转移到其余的unique_ptr,这样它自身就不再领有原来指针的所有权了。 如果心愿只有一个智能指针治理资源或治理数组就用unique_ptr,如果心愿多个智能 指针治理同一个资源就用shared_ptroweak_ptr弱援用的智能指针弱援用的智能指针weak_ptr是用来监督sharedjtr的,不会使援用计数加一,它 不治理shared_ptr外部的指针,次要是对了监督shared_ptr的生命周期,更像是 shared_ptr的一个助手。weak_ptr没有重载运算符桥口因为它不共享指针,不能操作资源,次要是为了 通过Shared_ptr取得资源的监测权,它的结构不会増加援用计数,它的析构不会缩小 援用计数,纯正只是作为一个旁观者来监督shmed_ph中关离得资源是否存在。weak_ptr还能够用来返回this指针和解决循环援用的问题。` 

2、linux中软连贯和硬链接的区别.

原理上,硬链接和源文件的inode节点号雷同,两者互为硬链接。软连贯和源文件的 inode节点号不同,进而指向的block也不同,软连贯block中寄存了源文件的路径名。 实际上,硬链接和源文件是同一份文件,而软连贯是独立的文件,相似于快捷方式,存 備看源文件的地位信息便于指冋。 应用限度上,不能对目录创立硬链接,不能对不同文件系统创立硬链接,不能对不存在 的文件创建硬链接;能够对目录创立软连贯,能够跨文件系统创立软连贯,能够 对不存在的文件创建软连贯。

八、中兴

1、线上CPU爆高,请问你如何找到问题所在。

答案:

1、top命令:Linux命令。能够查看实时的CPU应用状况。也能够查看最近一段时间 的CPU应用状况。

2、PS命令:Linux命令。弱小的过程状态监控命令。能够查看过程以及过程中线程的 以后CPU应用状况。属于以后状态的采栏数据。

3、jstack: Java提供的命令。能够查看某个过程的以后线程栈运行状况。依据这个 命令的输入能够定位某个过程的所有线程的以后运行状态、运行代码,以及是否死锁等

4、pstack: Linux命令。能够查看某个过程的以后线程栈运行状况。

2、红黑树如何插入和删除的

答案:

插入:

(1)    如果父节点为彩色,直接插入不解决

(2)    如果父节点为红色,叔叔节点为红色,则父节点和叔叔节点变为彩色,先人节 点变为红色,将节点操作转换为先人节点

(3)    如果以后节点为父亲节点的右节点,则以父亲结点为核心左旋操作

(4)    如果以后节点为父亲节点的左节点,则父亲节点变为彩色,先人节点变为红色, 以先人节点为核心右旋操作

删除:

(1)    先依照排序二叉树的办法,删除以后节点,如果须要转移即转移到下一个节点

(2)    以后节点,必然为这样的状况:没有左子树。

(3)    删除为红色节点,不须要解决,间接依照删除二叉树节点一样

(4)    如果兄弟节点为彩色,兄弟节点的两个子节点为彩色,则将兄弟节点变为红色, 将着色转移到父亲节点

(5)    如果兄弟节点为红色,将兄弟节点设为彩色,父亲结点设为红色节点,对父亲 结点进行左旋操作

(6)    如果兄弟节点为彩色,左孩子为红色,右孩子为彩色,对兄弟节点进行右旋操 作

(7)    如果兄弟节点为彩色,右孩子为红色,则将父亲节点的色彩赋值给兄弟节点, 将父亲节点设置为彩色,将兄弟节点的右孩子设为彩色,对父亲节点进行左旋

九、滴滴

1、寻找两个有序数组的中位数

double findliledianSortedArrays (vectoi<intnumsl, vector<int>& nums2) { double ret - ~1;vector<double> buff;//合并两个数组for (auto e : numsl)buff. push_back(e);for (auto a : nums2)buff. push_back(a);合并后的后果进行排序sort (buff. beginO, buff, end:));int size3 = buff. size();/依取中位数if (size3 % 2 == 0)[ret = ((buff[size3 / 2] + buff[size3 / 2 - 1]) / 2);}else{ret = buff[size3 / 2];}return ret;} 

2、c++实现线程平安的单例模式

懒汉模式:class singleton[protected:singletonO[p thr e ad_mut ex_ini t(&mutex);private:static singleton* p;public:static pthread__mutex_t mutex;static singleton* initance();pthread_mutex_t singleton::mutex;singleton* singleton::p = NULL;singleton* singleton::initance()[if (p == NULL)[p thr e ad_mut ex_lo ck(&mutex);if (p == NULL)p = new singletonO ;p thr e ad_mut ex_unlo ck(&mutex;;}return p;} 

企业级实战我的项目纲要,学完轻松待业☟

我都这么有诚意了你还不关注我???