二狗的面试题整理 其二

  之前看过某位大佬的博客,说咱们搞技术的常常参加一些面试是有些好处的。二狗比较认同这句话,一是可以长长见识,毕竟在熟悉的环境做就了容易固步自封。二是可以及时的了解市面的行情与自己的能力水平。哈,废话不多,记录一下最近遇到的一次面试题。

1.用递归计算出1,1,2,3,5,8,13 . . .第三十位是多少?

  很经典的斐波那契数列,用递归实现也比较容易。其实只需要在递归时额外传入一个depth参数,来计算递归深度,直到计算出第三十位即可。额外扯一句,用depth标识递归深度是个很常用的思想,在一些问题的求解时,甚至可以直接使用递归深度来作为递归终止条件。

  另外再稍微BB一下,在学习递归时其实有两点对二狗帮助很大。

  1.不要上来就尝试去写递归的代码,要先写出递推公式并找到递归终止条件,利用这两点来翻译成真正的代码。

  2.不要尝试用人脑去模拟递归的过程,人脑毕竟与电脑有很大的差别,如果你尝试这么做很容易让思维变得十分混乱。可以借助输出与log来查看每次递归的过程。

 

2.PDB文件是什么,调式的时候应该把PDB文件放到哪里。

  这道题目有一说一,我没有答上来。只是隐约记得本地Build生成的文件中每个dll文件通常会对应的pdb文件。

  PDB文件全名是Program Database File(哈,所以简写为什么不是PDF?),保存着调试和项目状态信息,使用这些信息可以对程序的调试配置进行增量链接。Visual Studio 调试器使用 EXE 或 DLL 文件中的 PDB 路径查找 project.pdb 文件。 如果调试器无法在该位置找到 PDB 文件,或者该路径无效,调试器将先搜索包含 EXE 的路径,然后搜索**“选项”对话框中指定的符号路径。 该路径通常是“符号”节点中的“调试”文件夹。 如果调试器无法找到 .PDB 文件,则显示“查找符号”**对话框,这将允许您搜索符号或向搜索路径添加其他位置。

  上述描述摘自微软给出的文档,英文版也贴一写:

  The Visual Studio debugger uses the path to the PDB in the EXE or DLL file to find the project.pdb file. If the debugger cannot find the PDB file at that location, or if the path is invalid, the debugger searches the path containing the EXE, and then the symbol paths specified in the Options dialog box. This path is generally the Debugging folder in the Symbols node. If the debugger cannot find a .PDB file, a Find Symbols dialog box appears, which allows you to search for symbols or to add additional locations to the search path.

  所以其实答案已经比较清楚了。PDB文件是保存着调试和项目状态信息的文件,通过它可以帮助我们进行调试。然后VS会默认在生成我们的exe或dll的路径下寻找pdb,如果找不到就会按照你的配置中指定的路径去寻找。至于配置的路径,就看你怎么定义了。

  

  这里笔者没有指定Pdb文件的路径~~。

 

3.XMLSerializer使用有哪些限制?

  嗯,二狗做过的项目大都是以Json格式传递数据,XML确实接触的不多。面试时只回答上了要求对象非空,想想还有点尴尬。。。

  XMLSerializer 对象使你能够把一个 XML 文档或 Node 对象转化或“序列化”为未解析的 XML 标记的一个字符串。而关于有哪些限制,笔者查到的内容如下:

XmlSerializer的有一些缺点。

  1. 必须知道所有的类型被序列化。通过界面,重新presents一个类型,序列化不知道你不能把它传递的东西。
  2. 在它不能做循环引用。
  3. 将序列化的同一个对象多次,如果对象图中多次引用。
  4. 在无法处理私有字段序列化。

 

4. 基础题目

int i = 12;
int j = i;
j = 13;

Console.WriteLine("i : {0}, j: {1}", i, j);

i = 14;

Console.WriteLine("i : {0}, j: {1}", i, j);

  输出结果,第一次i=12,j=13。第二次i=14,j=13。很简单的题目,值类型的变量,存储的就是本身的值。

 

5. 具体题目有些记不清楚了,总之是关于string的,当然原始的题目没有这么复杂啦。

 1             string s1 = "123";
 2 
 3             Console.WriteLine("s1 hash: {0}", s1.GetHashCode());
 4 
 5             string s2 = s1 = "456";
 6 
 7             Console.WriteLine("s1 hash: {0}, s2 hash: {1}", s1.GetHashCode(), s2.GetHashCode());
 8 
 9             string s3 = s1;
10 
11             Console.WriteLine("s1 hash: {0}, s2 hash: {1}, s3 hase: {2}", s1.GetHashCode(), s2.GetHashCode(), s3.GetHashCode());
12 
13             Console.WriteLine("s1: {0}, s2: {1}, s3: {2}", s1, s2, s3);
14 
15             s3 = "789";
16 
17             Console.WriteLine("s1 hash: {0}, s2 hash: {1}, s3 hase: {2}", s1.GetHashCode(), s2.GetHashCode(), s3.GetHashCode());
18 
19             Console.WriteLine("s1: {0}, s2: {1}, s3: {2}", s1, s2, s3);
20 
21             string s4 = "abc";
22             string s5 = s4;
23 
24             Console.WriteLine("s4: {0}, s5: {1}", s4, s5);
25             Console.WriteLine("s4 hash: {0}, s5 hash: {1}", s4.GetHashCode(), s5.GetHashCode());
26 
27             s5 = "def";
28 
29             Console.WriteLine("s4: {0}, s5: {1}", s4, s5);
30             Console.WriteLine("s4 hash: {0}, s5 hash: {1}", s4.GetHashCode(), s5.GetHashCode());
31 
32             string s6 = "xyz";
33             string s7 = "xyz";
34 
35             Console.WriteLine("s6 hash: {0}, s7 hash: {1}", s6.GetHashCode(), s7.GetHashCode());

 

  小伙伴们可以试一下看自己能不能全答对。这道题有些惭愧,因为毕竟比较基础,笔者的回答应该不是全对。

  首先要明确string是引用类型。也就说实际上s1等变量指向的只是一个地址,那我们就可以推断s2=s1可能是让s2和s1指向同一个地址。再有笔者之前有印象说是string是一旦赋值就不可以改变的,而这两点是有一些矛盾的。具体解释的话大家可以看一下园子里这篇文章,解释的很详细。传送门

  总结下来的话,string确实是引用对象没错,它的值也确实不会更改,每次试图更改的时候都会生成新的对象。但是还是要结合CLR中的字符串驻留技术,值相同的字符串会指向相同的地址。

下面是运行结果:

  这样总结来看,似乎string确实挺奇葩的。本身的个引用类型,“string s6 = "xyz"; string s7 = "xyz";” 却会指向相同的地址,有点反常识了哈哈。

 

6. Equals 和 == 的区别。

  简单来说,对于值类型,二者比较的都是具体的值,所以没区别。对于引用类型,== 比较的是两个对象的引用地址,而Equals就要看具体的实现了,如果你重写了对应的Equals的方法,就按照你的逻辑进行判断,默认情况是比较两个对象的内容的区别。

 

7. 深拷贝与浅拷贝的区别,有哪些对象使用的是深拷贝.

  第一问其实很简单,对于引用类型才有这样的区别,深拷贝会生成新的对象,浅拷贝只是复制了引用的地址。因此对于浅拷贝,会出现改变一个对象的值,另一个对象跟着改变的情况。第二问有些懵逼,一时没有好的思路,可能要结合具体的场景把。

 

8. 分布式系统怎么生成全局唯一的ID。

  这个题目说实话没有在现实场景中碰到过,毕竟接触的项目实在是有些浅显了。二狗当时写的答案是两种方式,

  1. 利用GUID+MAC地址的方式,当时的想法是GUID产生相同值的概率很低,再加上每台硬件唯一的MAC地址应该可以保证唯一。
  2. 所有申请操作都在主服务器上完成,由某台主服务器统一生成。

  百度了一下还有说由数据库自增统一生成的,emmm,感觉这种方式不是很友好。如果有不对的或者更好的方式欢迎拍砖和指教哈。

 

9. 最后一道是个算法题。详情可以查看leetcode第一题,两数之和。

  嗯,重温了一下,官方的一遍哈希法还是很骚气的,哈哈。多刷题还是有好处的,嘻嘻。

posted @ 2020-05-09 16:27  DogTwo  阅读(208)  评论(0编辑  收藏  举报