百度实习面试

本文总结了百度实习面试中涉及的C++ STL容器、智能指针、多态性、算法优化及设计模式等内容,深入剖析了map与hash_map、list与vector的区别,探讨了快速排序的稳定性改进及直方图最大面积计算等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前段时间找实习,投了百度几个部门,最终终于收到录用的通知,总结一下面试题目。


一、语言

1、C++STL里map与hash_map的区别

hash_map的用法和map是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。虽然对外部提供的函数和数据类型是一致的,但是其底层实现是完全不同的,map底层的数据结构是rb_tree而,hansh_map却是哈希表来实现的。

     总 体来说,hash_map 查找速度会比map快,而且查找速度基本和数据量大小无关,属于常数级别;而map的查找速度是log(n)级别。hash还有hash函数的耗时。当有100w条记录的时候,map也只需要20次的比较,200w也只需要21次的比较!所以并不一定常数就比log(n) 小!

    hash_map对空间的要求要比map高很多,所以是以空间换时间的方法,而且,hash_map如果hash函数和hash因子选择不好的话,也许不会达到你要的效果,所以至于用map,还是hash_map,从3个方面来权衡:查找速度, 数据量, 内存使用,还有一个就是你的经验!没有特别的标准

另外可以通过重写 hash_compair仿函数,更改里面关于桶数量的定义,如果取值合适,也可以得到更优的性能。而且如果你的数据是自定义的类型,必须要重写这个仿函数。可以模仿原来的写法,所有的成员函数,成员变量一个不能少!

参考博客:http://blog.youkuaiyun.com/cws1214/article/details/9842679


2、C++STL里list和vector的区别

vector为存储的对象分配一块连续的地址空间,因此对vector中的元素随机访问效率很高。在vecotor中插入或者删除某个元素,需要将现有元素进行复制,移动。如果vector中存储的对象很大,或者构造函数复杂,则在对现有元素进行拷贝时开销较大,因为拷贝对象要调用拷贝构造函数。对于简单的小对象,vector的效率优于list。vector在每次扩张容量的时候,将容量扩展2倍,这样对于小对象来说,效率是很高的。
list中的对象是离散存储的,随机访问某个元素需要遍历list。在list中插入元素,尤其是在首尾插入元素,效率很高,只需要改变元素的指针。
综上所述:
vector适用:对象数量变化少,简单对象,随机访问元素频繁
list适用:对象数量变化大,对象复杂,插入和删除频繁
最大的区别是,list是双向的,而vector是单向的。

参考博客:http://blog.163.com/lhl_soft/blog/static/20175000420120161422375/


3、堆和栈的区别

一个由c/C++编译的程序占用的内存分为以下几个部分 

1、栈区(stack)―   由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 

2、堆区(heap) ―   一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 

3、全局区(静态区)(static)―,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 

4、文字常量区  ―常量字符串就是放在这里的。 程序结束后由系统释放 

5、程序代码区―存放函数体的二进制代码。 

4、C++智能指针

智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露。它的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。

参考博客:http://blog.youkuaiyun.com/hackbuteer1/article/details/7561235


5、C++多态的实现

多态的本质简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
多态性在Object Pascal和C++中都是通过虚函数(Virtual Function) 实现的。

多态性是允许将父对象设置成为和一个或多个它的子对象相等的技术,比如Parent:=Child;
多态性使得能够利用同一类(基类)类型的指针来引用不同类的对象,以及根据所引用对象的不同,以不同的方式执行相同的操作。

参考博客:

http://yanlinjust79.blog.163.com/blog/static/169508482201152445213848/






http://blog.youkuaiyun.com/tujiaw/article/details/6753498


6、C++虚函数

虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。

参考博客:http://blog.youkuaiyun.com/haoel/article/details/1948051


7、C++指针和引用的区别

首先,引用不可以为空,但指针可以为空。前面也说过了引用是对象的别名,引用为空——对象都不存在,怎么可能有别名!故定义一个引用的时候,必须初始化。因此如果你有一个变量是用于指向另一个对象,但是它可能为空,这时你应该使用指针;如果变量总是指向一个对象,i.e.,你的设计不允许变量为空,这时你应该使用引用。如下图中,如果定义一个引用变量,不初始化的话连编译都通不过。

其次,引用不可以改变指向,对一个对象"至死不渝";但是指针可以改变指向,而指向其它对象。说明:虽然引用不可以改变指向,但是可以改变初始化对象的内容。例如就++操作而言,对引用的操作直接反应到所指向的对象,而不是改变指向;而对指针的操作,会使指针指向下一个对象,而不是改变所指对象的内容。

再次,引用的大小是所指向的变量的大小,因为引用只是一个别名而已;指针是指针本身的大小。

最后,引用比指针更安全。由于不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,因此引用很安全。对于指针来说,它可以随时指向别的对象,并且可以不被初始化,或为NULL,所以不安全。const 指针虽然不能改变指向,但仍然存在空指针,并且有可能产生野指针(即多个指针指向一块内存,free掉一个指针之后,别的指针就成了野指针)。

参考博客:http://blog.youkuaiyun.com/listening_music/article/details/6921608


8、C++动态绑定和静态绑定

静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。
动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。

只有虚函数才使用的是动态绑定,其他的全部是静态绑定。

参考博客:http://blog.youkuaiyun.com/chgaowei/article/details/6427731



8、java内存管理、内存泄露

Java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆(Heap)中分配的,所有对象的回收都是由Java虚拟机通过垃圾回收机制完成的。GC为了能够正确释放对象,会监控每个对象的运行状况,对他们的申请、引用、被引用、赋值等状况进行监控,Java会使用有向图的方法进行管理内存,实时监控对象是否可以达到,如果不可到达,则就将其回收,这样也可以消除引用循环的问题。在Java语言中,判断一个内存空间是否符合垃圾收集标准有两个:一个是给对象赋予了空值null,以下再没有调用过,另一个是给对象赋予了新值,这样重新分配了内存空间。

java内存泄露引起原因

长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。


二、算法

1、快速排序的优化

快速排序是不稳定的排序,怎么改成稳定的排序

快速排序最差时间复杂度是o(n的平方),怎么避免这种情况

当数据长度较小时,用插入排序所需时间会少于快速排序


2、给定直方图,每一小块的height由N个非负整数所确定,每一小块的width都为1,请找出直方图中面积最大的矩形。 如下图所示,直方图中每一块的宽度都是1,每一块给定的高度分别是[2,1,5,6,2,3]: 那么上述直方图中,面积最大的矩形便是下图所示的阴影部分的面积,面积= 10单位。 请完成函数largestRectangleArea,实现寻找直方图中面积最大的矩形的功能,如当给定直方图各小块的高度= [2,1,5,6,2,3] ,返回10。

扫描,保持一个严格单调递增的栈。所有不高于被扫描元素的元素出栈,然后被扫到的元素入栈(相等的情况不入栈),同时更新尝试更新最大面积(通过栈顶两元素,空状态可以认为是高度0。根据维护的性质,可以保证这两个元素之间所有元素的高度都不低于当前元素)。元素需要保存完整的坐标(而不仅仅是高度,因为计算面积需要)。

参考博客:http://blog.youkuaiyun.com/jiyanfeng1/article/details/8067282


3、不用除法求:

A和B都是数组

其实就是需要考虑怎么减少重复计算

方法一:

用动态规划的思想,存储所有结果

比如先建立一个二维数组C,C[i,j]表示A[i]*A[i+1]*......*A[j],

先计算对角线上的值,然后向右上角扩展。B[j]=C[1,j-1]*C[j+1,n]。


方法二:

在纸上写几项,找出规律,可以用两个数组C和D,C[i]=A[1]*A[2]*....*A[i],D[i]=A[n-0]*A[n-1]*.....*A[n-i]

B[i]=C[i-1]*D[n-i+1]


4、在一个严格递增的数组A中找出A[i]=i

这题让在纸上写的,主要用二分法来求,需要考虑数组为空、数组长度为0、找不到该值等情况。


5、两个服务器通过网络连接,两个服务器保存1T的相同的数据。现在只修改其中一个服务器上的少量数据,求快速找出修改了哪些地方。

因为数据量大,且通过网络连接,不能把两个数据相应的位置相互比较。

所以可以通过md5算法把大量数据映射成少量数据,然后再进行比较。

需要考虑的问题是:可以用二分法逐步找到修改的数据

                             用二分法会有重复计算,可以从底往上进行md5算法

                             内存大小有限制,需要把数据分成可以加载到内存的大小


6、计算一个数字转换成二进制后含有的1的个数


7、一个数组除了一个数只出现一次,其他数均出现两次,求找出这个数


这两题在剑指offer上都有




三、设计模式

1、状态模式

2、观察者模式


四、机器学习

1、支持向量机

2、聚类和分类


先写到这,有些内容之后再补充,有不对的请指出。



                            





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值