面试总结
写在前言
- 这次是通过官网投递简历,好像算是提前批,总结一下面试中遇到的问题。面试时间在腾讯会议中设定为1个小时,但实际时间并未到1个小时(45Min)就结束了,可能跟我回答问题的情况有关系。
项目相关(这部分占用了接近30分钟)
- 在简历中我写了三个参加的项目,面试官针对于每一个项目都扣得特别细致,针对其用到的算法实现细节。
- 注意:
面试官对一些没有什么技术难点的项目不感兴趣,但如果项目中有Unity、Unreal 中的内容,面试官还是比较感兴趣的部分,他还是会提问的,比如:我应用了Unity中的自动寻路功能,会提问具体如何实现。 - 项目中涉及到的算法,即使是小众,他可能不了解,但他也是会让你跟他讲具体实现,直到他大概听懂,注意:还有具体的实现中遇到的问题如何解决?采用什么步骤解决问题、数据结构等等
算法 + 语言基础知识 + 图形学
算法题
-
提问的是基本就是LeetCode第一题 : The Sum ,只是面试官没有对返回索引或者是返回两个数做限制
-
这个问题很简单,当时也是参考过题解,记得很清楚,所以答上了
问题的解法很多: -
map法(仅列举这个方法) 题目传送门
vector<int> twoSum(vector<int>& nums, int target) { int len=nums.size(); unordered_map<int,int> mymap(len); unordered_map<int,int>:: iterator it; for(int i=0;i<len;++i){ if((it=mymap.find(target - nums[i]))!=mymap.end()) return vector<int>{it->second,i}; else{ mymap.insert(pair<int,int>(nums[i],i)); } } return vector<int>{}; }
C++基础知识
哈希冲突有哪些解决方法?
- 1.开放定址法
用开放定址法处理冲突得到的散列(哈希)表叫做 闭散列表。
所谓开发定址法,就是由关键码得到的哈希地址一旦产生冲突,就去寻找下一个空的哈希地址,只要哈希表足够大,空的哈希地址总能找到,并将记录存入。 - 这个问题我只答出了完后移动一个位置和使用链表的形式,没有答完整
找到下一个空哈希地址的方法:
- ①线性探测法
当发生冲突时,线性探测法从冲突位置的下一个位置起,依次寻找空的散列地址。公式为
H i =(H(key)+d i )%m (d i=1,2,3,4,…,m-1) m 为闭散列表的长度。 - ②二次探测法
当发生冲突时,二次探测法寻找下一个散列地址的公式为
H i =(H(key)+d i )%m (d i =1 2 ,-1 2 ,2 2 ,-2 2 ,…,q 2 ,-q 2 )
m 为闭散列表的长度。 - ③随机探测法
当发生冲突时,随机探测法探测下一个散列地址的位移量是一个随机数列,公式为
Hi=(H(key)+di)%m(di是一个随机数列) m 为闭散列表的长度。
- 2.拉链法
- ①用拉链法处理冲突构造的散列表叫做开散列表。
拉链法的基本思想是,将所有散列地址相同的记录,即所有关键码为同义词的记录存储在一个单链表中——称为同义词子表,在散列表中存储的是所有同义词子表的头指针。
虚函数的概念?C++如何实现的虚函数?
- 这部分我答得有点差,我说虚函数是在基类中定义了,由子类进行实现,这也体现了类的多态性。
- 详细讲解见 ---->这是一篇写的比较详细的博客
C++11有哪些新特性?
cast 强制转换
- 共四种: static_cast,const_cast,reinterpret_cast,dynamic_cast , 因强制转换存在风险,故引入强制转换机制
- 目的:
为了克服C语言强制类型转换的以下三个缺点:- 没有从形式上体现转换功能和风险的不同
- 将多态基类指针转换成派生类指针时不检查安全性,,即无法判断转换后的指针是否指向一个派生类对象
- 难以在程序中定位进行了强制转换的地方
static_cast强制转换
-
程序上标明进行转换 基本等价于隐式转换 是适用于明确需要隐式转换的地方
-
可用于低风险的转换
整型和浮点型
字符和整型
转换运算符
*空指针转换为任何目标类型 -
不可以用于风险较高的转换
不同类型的指针之间的转换
整型和指针之间的互相转换
不同类型的引用之间的转换int n=5;
父类转子类 不安全
子类转父类 安全
CFather* pFather = nullptr;//父类指针 CSon* pSon = nullpter; //子类指针 //父类转子类 不安全 pSon=pFather;//隐式转换 编译不会通过 pSon=static_cast<CSon*> pFather;//静态转换 不安全 没有提供运行时检测 //子类转父类 安全(子类多 包含着父类 不会超过父类的界限) pFather=pSon; pFather=static_cast<CFather*>pSon;
const_cast
仅用于指针、引用、this指针 的转换
-
应用1: 去掉函数前的限制
class A{ public: CTest():m_nTest(2){}//初始化列表 对成员m_nTest进行赋值 //常成员函数 void foo(int nTest) const{ //void* p=this;//无法隐式转换 //m_nTest=nTest;//错误 const_cast<CTest*>(this)->m_nTest=nTest;//可执行 相当于去掉了常成员函数中的const常量限制 } public: int m_nTest; }
reinterpret_cast
- 显示强转,各种类型的指针间强行装换
int* p=n;
char* q=p;
pFather=static_cast<CFather*>pSon;
dynamic_cast
- 用于虚函数的基类与派生类之间的指针、引用的转换
- 基类必须具备虚函数(具有多态类类型的向下转换使用)
- 运行时检查,转型不成功则返回NULL
- 非必要不使用
- 可以在运行时做检测(依赖RTTI,有额外的开销,只有向下转换才会使用),如果会出错,则转换指向NULL,代码不会报错
图形学、渲染问题
- 渲染管线的顺序
- 在三维空间中,如何判断一个点在一个三角面中
注:
- 关于上面问题的解答(不知道是不是说全或说正确了,希望大家可以一起讨论,并指点迷津)