百度暑期实习
一面 2021.05.31
-
C++构造函数(拷贝构造函数,赋值的时候发生了什么,为什么要用引用)
当定义一个对象时,会按顺序做2件事情:
分配好内存(非静态数据成员是未初始化的)
调用构造函数(构造函数的本意就是初始化非静态数据成员)
显然上面代码中,CLS obj;这里已经为obj分配了内存,然后调用默认构造函数,但是默认构造函数还未执行完,却调用了另一个构造函数,这样相当于产生了一个匿名的临时CLS对象,它调用CLS(int)构造函数,将这个匿名临时对象自己的数据成员m_i初始化为0;但是obj的数据成员并没有得到初始化。于是obj的m_i是未初始化的,因此其值也是不确定的
用值传递时,会多次调用拷贝构造函数,以及析构函数,非常影响性能
如果一个函数是pass-by-value,那么传入函数内部时,编译器会调用copy构造函数构造一份实参的副本,执行函数内部的逻辑,然后将这个副本返回,所以我们只是传值的话,是不会对原实参作改动的。
如果设计的基类中有virtual函数,那么pass-by-reference还避免了对象切割(slicing)问题,对象切割不是多态,多态是通过指针或者引用实现的,而对象切割是派生类直接向基类传递或者强制类型转换的时候,自己(基类)的部分在转换时丢失了,就像被切割了一样。
当然,对于built-in types , STL迭代器对象 , 函数对象可以用值传递,性能也不错 -
C++析构函数如果直接free空间,不调用析构函数,会怎么样
-
new 和malloc的区别
从表面上来看, new 返回指定类型的指针,并且可以自动计算所需要大小:
而 malloc 则必须要由我们计算字节数,并且在返回后强行转换为实际类型的指针:
在new中,先由operator new调用malloc申请了对象数据存储大小(非全局静态成员变量+虚函数表指针大小*数量)的空间,然后赋给一个空指针,然后静态转型为目标型的指针,赋值给刚开始定义对象类型指针,然后调用了类的构造函数,对内对中的对象空间初始化赋值。
在delete中,则是先调用了对象的析构函数,然后调用operator delete来free空间。 -
智能指针
-
Raii
RAII是Resource Acquisition Is Initialization(wiki上面翻译成 “资源获取就是初始化”)的简称,是C++语言的一种管理资源、避免泄漏的惯用法。利用的就是C++构造的对象最终会被销毁的原则。RAII的做法是使用一个对象,在其构造时获取对应的资源,在对象生命期内控制对资源的访问,使之始终保持有效,最后在对象析构的时候,释放构造时获取的资源。
其实就是把资源都放到类中,利用类的构造和析构函数去进行资源管理 -
linux socket编程
socket() bind() listen() connect() accept() close() read() write() 三次握手 四次挥手 -
数据库b+树存储
-
redis Zset底层数据类型(跳表?
string
简单动态字符串(simple dynamic string,SDS)的抽象类型,并将 SDS 作为 Redis的默认字符串表示。相对于 C 语言对于字符串的定义,多出了 len 属性以及 free 属性,常数复杂度获取字符串长度,
链表
双端,无环,带长度计数,可以保存各种类型
整数集合
压缩列表
压缩列表的原理:压缩列表并不是对数据利用某种算法进行压缩,而是将数据按照一定规则编码在一块连续的内存区域,目的是节省内存。 -
山峰数组找最大值(二分
其实就是正常的二分算法,如果直接排序在找到最大值是O(nlogn),如果直接遍历数组,记住最大值是O(n),二分的话是O(logn)
二分就是要确定好循环的条件,终止条件,以及缩小区间的条件
二面 2021.06.03
- 引用和指针的区别,为什么没有引用的引用
引用不是对象,所以不能定义引用的引用(在内存中没有实际的空间?
但是类型别名或模板参数时可以间接定义引用的引用,只是为std::move/std::forward使用,一般不会这么定义。 - 如何只在堆或者栈上实例化对象
类的两种实例化方法:
Class A{
public:
int a;
};
void main(){
A test; //栈上实例化
A.a = 10;
A *p = new A;//堆上实例化
delete p;
p = NULL;
}
只在栈上实例化(禁用new运算符)
class A{
private:
void* operator new(size_t t){}
void operator delete(void* ptr){}
public:
A();
~A();
};
// new操作符是C++内建的,所以必须要先认清一个事实即:
// new operator总是先调用operator new,所以我们只要对new操作符进行重载
// 并将它声明为private的,就能保证不能再使用new实例化对象
只在堆上实例化(私有析构函数)
// 私有析构函数
class A{
public:
A(){}
void destroy(){delete this;}
private:
~A(){}
};
// 当析构函数被私有化之后,若在栈上实例化对象,编译器先会检查该对象的析构函数是否可用
// 如果不可用,则会报错。在堆上释放对象时,若不调用delete就不会发现析构函数不可访问。
// 私有构造函数(单例模式)
class B{
public:
static B* GetInstance(){
return (new B);
}
void destroy(){delete this;}
private:
B(){}
~B(){}
};
void main(){
B *p = B::GetInstance();
// ...使用p
B::destroy();
return
}
// static公有成员,因为它们独立于class对象之外,不必产生对象也可以使用它们
- malloc和new的区别
- http协议
- 数据库事务,隔离条件,事务的作用是什么
- 双向链表的拷贝
设计双向链表的结构,类似于LRU,首先连接好头尾节点,然后每new一个节点,插入到头部/尾部
不要被单向链表的复制误导,如果一直向下移动复制的话,前向节点就连不上了
三面hr
当时因为临时有事,是电话面的,直接在地铁里说了半个小时左右
主要就是问一些项目的细节,以及常规的hr面,还问什么时候能来实习
最后给了offer,但是考虑了一下,还是留在了字节继续实习
蔚来后端(挂)
笔试7.18
- 中间件:是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源,中间件位于客户机服务器的操作系统之上,管理计算资源和网络通信。不在内核里
- bash命令1>&2;0:标准输入(stdin),1:标准输出(stdout),2:标准报错输出(stderr);>输出重定向,< 输入重定向;标准输出重定向到标准报错输出
- 30分钟有车的概率是0.95,那么30分钟没有车的概率就是0.05,我们可以这么理解,30分钟没有车就相当于3个10分钟连续没有车,并且每个10分钟都是独立的,设10分钟内有车通过的概率为x,那么列出公式有:(1-x)³=0.05,1-x=0.368,x=0.632.于是,有车通过的概率就是0.632.
- 1B=8bits (255) 10801024分辨率为1B1080*1024=1MB
- 直方图最大矩形面积,找到每个列前后的最大宽度,算每次最大面积,取max
- 括号匹配,栈
- 子数组的最大和,从前往后求sum,如果sum<0,sum=A[i]
- 电话号码数字字母组合,dfs深度优先遍历,回溯??列出所有可能性
shopee后端(已offer)
笔试7.19
- WASD移动坐标,很坑的是,题目只说了大写字母,但是在测试样例里却有小写字母,导致一直不是100%,都快怀疑人生了
- 包含target字符串的最长子串,滑动窗口+map,注意count加减一定要保证map中匹配都是0
- 杨辉三角,规律a[i][j]=a[i-1][j-1]+a[i-1][j],a[i][0]=1,a[i][i]=0
一面
- 忘了具体时间和内容了当时在实习,比较忙
二面8.22
- 主要是问一些项目的细节,并没有实际写代码
- 场景题:微博点赞场景设计。高并发写入用消息队列进行削峰
hr面8.23
- 常规hr面
- 说是两周内给结果
商汤后端go(已offer)
一面7.21
- 项目介绍
- 图数据库、mysql、nosql数据库对比
- mysql底层存储引擎相关
- go的GPM介绍
- 有向无环图的广度遍历
- 杨氏矩阵第k大数,只说了大概思路,好像不是最优解
- 大概一个小时
二面7.26
- 项目介绍
- 算法题:判断链表是否有环
- 线程和进程区别,通信方式
- 其他记不太清了…
三面7.29
- 项目介绍,针对项目详细问实现的方案
- 算法题:LRU或者搜索二叉树转单链表
- redis跳表
- mysql删表语句
- http状态吗 3xx 重定向的区别
- 输入网址之后的流程
- 场景设计题,GPU worker的调度问题,可以加一个调度者的角色,掌控资源和任务,每次任务来了,把所需要的资源配到任务上,一并发送给worker
- 问字节实习可不可以转正,说做的内容没有深度,对未来发展不利之类的…不知道是想要让我去商汤还是咋样…许愿hr面,目前走的最远的一家公司,求求了…
hr面
- 简单问一些常规问题
- 过几天就收到了意向书,第一个offer 哭了
京东C++搜索(挂)
一面7.23
- 项目介绍
- tcp三次握手,四次挥手
- const修饰成员函数 在最前面 在最后面
- 虚函数
- map和unordered_map的底层
- 智能指针
- 大概只有20+min,都是常规的问题,没有算法题
- 挂的莫名奇妙,本来就没有问啥,面试官自己有时候还不太确定问题的答案,就把我挂了
爱奇艺go
一面7.30
- 自我介绍
- 死锁,及其四个条件
- go的gpm调度模型
- OLAP和OLPP
- 算法题:如何让00110->00111,变成单增需要变化的最少位数。思路是可以倒着来,单增的是有限的,00001,00011,00111等,只需要计算每种变化的位数,取最小的。但是计算每种变化的位数,只想到了遍历O(n)的算法,总的是O(n2),应该可以有时间复杂度更小的。对于每个字符串00110,可以遍历的时候,做一个map,记住每一位之后有多少个1,比如m[4]=0,m[3]=1,m[2]=2,m[1]=2,m[0]=2,这样与00111相比较的时候,就是3-m[3] = 1,总的复杂度变成了O(n)
二面
- 忘了时间
- 算法题:字典树,听到的时候人都傻了,我都不知道字典数是啥概念。好在慢慢提醒,写出了一点点思路吧。后来发现字典数是es储存底层的一部分,估计也是因为这问我的
三面8.18
- 仔细怼项目,问的很细致而且很原理,问到最后我都觉得我们当时方案设计有问题,面试官说的很有道理。总的来说面试体验不错
- TODO:RESTFUL协议,数据库三大范式
四面8.23
- 看起来就是个大佬级别的人物,问了几个三面漏掉的问题,也是和项目相关
- 半个小时左右
- 据说还有一面,哭了
OPPO后端
一面8.23
- 主要都是聊项目
- mysql查询计划,type,index,range?
- mysql三大范式,老是记不住
- redis持久化相关
- BIO、NIO、AIO这都是啥
- 压缩链表
二面9.3
- 布隆过滤器缺点
- 当一个元素被加入集合时,通过 K 个 Hash 函数将这个元素映射成一个位阵列(Bit array)中的 K 个点,把它们置为 1。
检索时,我们只要看看这些点是不是都是 1 就(大约)知道集合中有没有它。
值得注意的是:如果这些点有任何一个 0,则被检索元素一定不在。
如果都是 1,则被检索元素很可能在。 - 空间效率和查询时间都远远超过一般的算法,布隆过滤器存储空间和插入 / 查询时间都是常数O(k)。
另外, 散列函数相互之间没有关系,方便由硬件并行实现。
布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。 - 误算率是其中之一。随着存入的元素数量增加,误算率随之增加。但是如果元素数量太少,则使用散列表就可以。
另外,一般情况下不能从布隆过滤器中删除元素 - 如何用2g内存搜索4G文件:哈希映射到块,布隆过滤器?
百度-深度学习架构(挂)
一面8.20
- C++基础知识 问的不算太难
- 算法题:顺时针打印二维矩阵,写得有点bug,展现了一波现场调试能力
二面8.20
- 一面完15min进行的二面
- 算法题:层序遍历打印二叉树
- 最后一直问你看你写的算法有没有什么问题,原来是想说内存管理之类的,new完之后要delete,函数参数传参不能用值传递等等。根本没往这方面想,不知道还有没有后续
百度-搜索产品部
一面8.24
- C++基础知识
百度-知识图谱部
一面8.30
- 项目介绍
- 常规基础知识
- 算法题:反转字符串,比较简单,但是忘了go的字符串是不能直接赋值的
二面8.31
- 项目介绍
- 面试官貌似对我机器人本专业的东西很感兴趣,问了半天
- 算法题:在字符串中找到ip地址并打印,做的不是很好,大概说了下思路
- 吐槽一下百度的如流会议,每次共享屏幕都卡死了,太难用了
三面9.2
美团-后端开发
一面8.24
- 合并有序排序数组
- 判断字符串是不是回文串
二面8.26
- tcp粘包、拆包
- 长链接,短链接
- 进程、线程、协程各自特点
- sql定义类型和查询类型不一致,怎么走索引
hr面8.30
- 比较常规的hr面试