求职季,真的会让一个人变得有些不一样吧,比如我,对于一个菜鸟来说,最近一段时间焦虑不安外加有点自闭...

前段时间在校内网上看到了陌陌科技内推计算机视觉算法工程师和机器学习算法工程师的消息,抱着试试的心态整理了一份简历按照提供的邮箱投出去了,我想这次应该又是石沉大海了吧,谁想在一周前闷热的一天在嘈杂的餐厅接到了陌陌科技HR的电话,一周后的周五下午4点在西安的一家咖啡馆参加面试。我问清了时间地点并道谢了HR后并挂了电话继续吃饭。

好吧,这周每天都有各个公司的笔试,外加这周周五上午的组会轮到我做组会汇报,我心里预估了一下时间安排,确实没时间来准备陌陌的面试,心想,就这样吧,面挂了就当积累经验吧...

时间很快就来到了周四晚上,当我9点做完招商银行的网上笔试后,打来之前没有写完的明天组会汇报的ppt接着写了起来,前两天已经连续凌晨2点回宿舍了,今晚不知何时能回。我主要给大家汇报一下近期的工作以及一篇临时看的发表在ICB2018上的使用GAN来完成从热红外到可见光的跨频谱人脸匹配的文献。时间来到11点半,ppt算是写得差不多了,但是文献中还是有很多细节问题因为时间关系没有搞懂,这篇文献里最大创新点也就是所提出的损失函数理解得云里雾里,我是继续加班搞懂才回宿舍呢,还是就这样将这个问题放在组会上大家一起讨论,可是明天还得早起啊。有那么一瞬间,我感觉呼吸不太顺畅,身体超负荷运转已经吃不消了。我选择回宿舍休息,就这样吧...

昨晚还是没有睡好,已经很久没有睡好觉了,不过相对于前两天,已经很不错了,9点组会开始,疲倦始终围绕着我,不出所料,这次组会因为各种因素我算是搞砸了...

组会完后,回到实验室给手机充电,打印了一份简历,吃完午饭回来打开百度地图搜索那家咖啡馆的地理位置并做好时间路线规划,等待手机充满电后我便出发了,下午3点我提前一个小时到了那家咖啡馆,我微信上给HR发消息说我到了进门之后怎么走,那位帅气的HR带我进了咖啡馆,问了下我的姓名和求职岗位,带我去签完到后给我找一个位置并了给了我一张A4纸,然后就是用自己熟悉的语言实现两道算法题,我周围的人都是今天来面试陌陌的,他们都在认真的低着头写代码。

第一题是实现输出一个长度为n的无序数组中的前k个最小值:

我能想到的就是先通过各种排序算法将数组排序,然后输出前k个最小值就行了,但是这并不是最好的方式,会造成复杂度比较高,因为只需要输出前k个最小值,剩下的n-k个数值不需要考虑。那么通过排序算法只需要排前k个数值ok了,不同的排序算法时间复杂度都是不一样的,比如比较容易实现的选择排序和冒泡排序平均情况下都是O(n2),若只需要找到前面的k个值复杂度也要O(n*k),若使用快速排序,复杂度近似O(n),如果使用堆排序,复杂度近似O(nlogk),下面基于堆排序给出解题思路以及python3代码:

方法是维护k个元素的最大堆,即用容量为k的最大堆存储最先遍历到的k个数,并假设它们即是最小的k个数,建堆费时O(k)后,有k1<k2<...<kmax(kmax设为大顶堆中最大元素)。继续遍历数列,每次遍历一个元素x,与堆顶元素比较,x<kmax,更新堆(用时logk),否则不更新堆。这样下来,总费时O(k+(n-k)*logk)=O(n*logk)。此方法得益于在堆中,查找等各项操作时间复杂度均为logk,python3代码如下:

 1 # -*- coding: utf-8 -*-
 2 """
 3 Created on Sun Sep  2 17:16:36 2018
 4
 5 @author: aoanng
 6 """
 7
 8 def create_heap(lyst):
 9     #创建数组中前k个数的最大堆
10     for start in range((len(lyst) - 2) // 2, -1, -1):
11         sift_down(lyst, start, len(lyst) - 1)
12
13
14     return lyst
15
16 # 堆排序,对于本问题用不着
17 def heapSort(lyst):
18     # 堆排序
19     for end in range(len(lyst) - 1, 0, -1):
20         lyst[0], lyst[end] = lyst[end], lyst[0]
21         sift_down(lyst, 0, end - 1)
22     return lyst
23
24 # 最大堆调整
25 def sift_down(lst, start, end):
26     root = start
27     while True:
28         child = 2 * root + 1
29         if child > end:
30             break
31         if child + 1 <= end and lst[child] < lst[child + 1]:
32             child += 1
33         if lst[root] < lst[child]:
34             lst[root], lst[child] = lst[child], lst[root]
35             root = child
36         else:
37             break
38
39
40 #测试
41 if __name__ == '__main__':
42     list1 = [50, 45, 40, 20, 25, 35, 30, 10, 15]
43     k = 4 #设置需要输出的前k个最小值
44     list_n_k = list1[k:]
45     heap_k = create_heap(list1[:k]) #将数组前k个数创建最大堆,并假设它们是最小的k个数
46     for i in range(len(list_n_k)):
47         if list_n_k[i]<heap_k[0]:
48             heap_k[0] = list_n_k[i]
49             heap_k = create_heap(heap_k) #更新堆
50     print(heap_k) #输出前k个未排序的最小值
51
52     #若需要,则可以对堆进行排序
53     heap_k_sort = heapSort(heap_k)
54     print(heap_k_sort)

第二题是给出一个n*n的矩阵,将其逆时针旋转90度,但是不能开辟新的内存空间:

这题的前提是必须在原数组上进行旋转操作,只要搞清楚矩阵中元素旋转的规律就容易求解了,那就是当前元素ai,j经过逆时针旋转90度后有ai,j=aj,(n-i)的关系。

写完这两道算法题后,我检查了两遍并在那儿扣手机,hr看见我写完之后过来收走了我的作业,让我等待一会儿,大概20分钟后一位技术面试官带着我的简历以及之前写好的算法题过来找我,第一轮技术面试便开始了。

我先简单的自我介绍后,面试官看着我的写的那两道算法题聊了起来,让我说说我的思路,我说第一题其实就是一个排序算法问题,然后输出前k个值就好,看见我用的选择排序算法,面试官指出了疑问,说这样时间复杂度会比较高,然后问我有没有其他的思路,我说可以只需要排前k个值将时间复杂度降到O(n*k),面试官最后逐步的引导我,说用最大堆会比较好,总之面试官人很nice,问到我不会的,总是在引导我。

然后就是介绍我简历中做过的几个项目,项目当中有用到深度学习平台tensorflow和CNN网络架构以及一些机器学习算法。面试官逐个问我,比如在ttensorflow中怎样构建一个cnn网络,防止过拟合的一些tips,Dropout是怎样工作的等等,然后让我手写在tensorflow中怎样保存模型和加载模型,tf.get_variable和tf.Variable的区别,tf.variable_scope和tf.name_scope的用法和区别,这些其实我平时项目中也有用到,平时也关注过这个问题,只是没有上心,当时没有回答上来,然后面试官大致的给我讲了一下原理就跳过这个问题了,回来后我又在网上查了一下资料,总结如下:

tf.variable_scope和tf.name_scope的用法:

tf.variable_scope可以让变量有相同的命名,包括tf.get_variable得到的变量,还有tf.Variable的变量

tf.name_scope可以让变量有相同的命名,只是限于tf.Variable的变量

例如:

 1 import tensorflow as tf;
 2
 3 with tf.variable_scope('V1'):
 4     a1 = tf.get_variable(name='a1', shape=[1], initializer=tf.constant_initializer(1))
 5     a2 = tf.Variable(tf.random_normal(shape=[2,3], mean=0, stddev=1), name='a2')
 6 with tf.variable_scope('V2'):
 7     a3 = tf.get_variable(name='a1', shape=[1], initializer=tf.constant_initializer(1))
 8     a4 = tf.Variable(tf.random_normal(shape=[2,3], mean=0, stddev=1), name='a2')
 9
10 with tf.Session() as sess:
11     sess.run(tf.global_variables_initializer())
12     print (a1.name)
13     print (a2.name)
14     print (a3.name)
15     print (a4.name)
16
17 #输出:
18 '''
19 V1/a1:0
20 V1/a2:0
21 V2/a1:0
22 V2/a2:0
23 '''

如果将上边的tf.variable_scope换成tf.name_scope将会报错:

Variable a1 already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope?...

改成如下这样就ok了:

 1 import tensorflow as tf
 2
 3 with tf.name_scope('V1'):
 4 #    a1 = tf.get_variable(name='a1', shape=[1], initializer=tf.constant_initializer(1))
 5     a2 = tf.Variable(tf.random_normal(shape=[2,3], mean=0, stddev=1), name='a2')
 6 with tf.name_scope('V2'):
 7 #    a3 = tf.get_variable(name='a1', shape=[1], initializer=tf.constant_initializer(1))
 8     a4 = tf.Variable(tf.random_normal(shape=[2,3], mean=0, stddev=1), name='a2')
 9
10 with tf.Session() as sess:
11     sess.run(tf.global_variables_initializer())
12 #    print (a1.name)
13     print (a2.name)
14 #    print (a3.name)
15     print (a4.name)
16
17 #输出:
18 '''
19 V1/a2:0
20 V2/a2:0
21 '''

接下来看看tf.Variable和tf.get_variable()的区别

在tensorflow中,tf.Variable和tf.get_variable()两个op分别用来创建变量。

tf.Variable()总是创建新的变量,返回一个variable,可以定义名字相同的变量,若给出的name已经存在,会自动修改name,生成个新的:

1 import tensorflow as tf
2 w_1 = tf.Variable(3,name="w_1")
3 w_2 = tf.Variable(1,name="w_1")
4 print (w_1.name)
5 print (w_2.name)
6 #输出
7 #w_1:0
8 #w_1_1:0

tf.get_variable()不可以定义名字相同的变量,tf.get_variable函数拥有一个变量检查机制,会检测已经存在的变量是否设置为共享变量,如果已经存在的变量没有设置为共享变量,TensorFlow 运行到第二个拥有相同名字的变量的时候,就会报错。
不同的变量之间不能有相同的名字,除非你定义了variable_scope,这样才可以有相同的名字。

1 import tensorflow as tf
2
3 w_1 = tf.get_variable(name="w_1",initializer=1)
4 w_2 = tf.get_variable(name="w_1",initializer=2)
5 #错误信息
6 #ValueError: Variable w_1 already exists, disallowed. Did
7 #you mean to set reuse=True in VarScope?

tf.get_variable一般和tf.variable_scope配合使用,用于在同一个的变量域中共享同一个变量。

如何在tensorflow中保存和加载模型呢?

构建网络中加入:saver = tf.train.Saver()

然后在session会话中:saver.save(sess, "./model/model.ckpt")

加载模型:

构建网络中需要和之前一样,然后在session会话中加载模型:

saver.restore(sess, "./model/model.ckpt")

然后和面试官讨论一些机器学习算法的问题,诸如LR和SVM的区别,随机森林和GBDT区别,xgboost以及最优化算法的原理等等,很快一个多小时就过去啦,感觉自己表现得不是太好,但是和面试官还是挺聊得来的,面试的最后,面试官问我对一些经典的数据结构熟悉不?我说还可以,然后他让我现场写一个单链表的逆序,很简单的问题,我却没写出来,我曾经看过java版本和c版本的数据结构与算法,前不久也看过用python实现的数据结构与算法,但是这个时候我却卡住了。10分钟后面试官看我连这个简单的问题都没写出来,笑着对我说该不该给我第二轮技术面的机会,然后第一轮技术面就这样结束了,让我在旁边的椅子上稍等一下...

等的过程中,我拿出手机百度了下单链表的逆序如何实现,恍然大悟的同时也有点懊恼,参考网上的答案,实现如下:

循环反转单链表:

 1 #定义一个单链表节点
 2 class ListNode:
 3     def __init__(self,x):
 4         self.data = x
 5         self.next = None
 6
 7 def nonrecurse(head):              #循环的方法反转链表
 8     if head is None or head.next is None:
 9         return head
10     pre=None
11     cur=head
12     h=head
13     while cur:
14         h=cur
15         tmp=cur.next
16         cur.next=pre
17         pre=cur
18         cur=tmp
19     return h
20
21 head=ListNode(1)    #测试代码
22 p1=ListNode(2)      #建立链表1->2->3->4->None;
23 p2=ListNode(3)          #head->p1->p2->p3->None
24 p3=ListNode(4)
25 head.next=p1
26 p1.next=p2
27 p2.next=p3
28
29 p=nonrecurse(head)   #输出链表 4->3->2->1->None
30 while p:
31     print (p.data)
32     p=p.next

递归实现单链表反转:

 1 class ListNode:
 2     def __init__(self,x):
 3         self.val=x;
 4         self.next=None;
 5
 6
 7 def recurse(head,newhead):    #递归,head为原链表的头结点,newhead为反转后链表的头结点
 8     if head is None:
 9         return ;
10     if head.next is None:
11         newhead=head;
12     else :
13         newhead=recurse(head.next,newhead);
14         head.next.next=head;
15         head.next=None;
16     return newhead;
17
18 head=ListNode(1);               #测试代码
19 p1=ListNode(2);                 # 建立链表1->2->3->4->None
20 p2=ListNode(3);
21 p3=ListNode(4);
22 head.next=p1;
23 p1.next=p2;
24 p2.next=p3;
25 newhead=None;
26 p=recurse(head,newhead);           #输出链表4->3->2->1->None
27 while p:
28     print (p.val)
29     p=p.next;

接下来就是技术第二面了,不说了,说多了都是泪...

参考:

  1. 窥探算法之美妙---寻找数组中最小的K个数&python中巧用最大堆
  2. 程序员编程艺术:第三章、寻找最小的k个数
  3. tf.variable_scope和tf.name_scope的用法
  4. tf.Variable()与tf.get_variable()与不同之处
  5. TensorFlow模型保存和加载方法
  6. 单链表反转python实现

转载于:https://www.cnblogs.com/aoanng/p/9581612.html

第一篇博客--记面陌陌科技计算机视觉算法工程师被刷经历(附面试过程中被问倒的一些算法题分析)...相关推荐

  1. 记面陌陌科技计算机视觉算法工程师被刷经历(附面试过程中被问倒的一些算法题分析)

    转载过来的,原文:https://www.cnblogs.com/aoanng/p/9581612.html 求职季,真的会让一个人变得有些不一样吧,比如我,对于一个菜鸟来说,最近一段时间焦虑不安外加 ...

  2. C博客作业00--我的第一篇博客

    这个作业属于哪个班级 C语言–网络2011/2012 这个作业的地址 C博客作业00–我的第一篇博客 这个作业的目标 学习Makdown语法,对本专业及C语言课程有个简单了解,记录自学慕课视频的笔记. ...

  3. 学习日志:第一篇博客

    小郝的第一篇博客 记录自己未来学习的过程--自我认知 文章目录 小郝的第一篇博客 一.做出改变 二.自我介绍 三.具体实现 四.总结 一.做出改变 在很久之前就有写博客这个想法,但一直没有付诸行动,疫 ...

  4. 【我的第一篇博客】——上个月学习总结(4月)

    大家好,我是monitor_sun 目录 前言 学习月总结 1.复盘上个月(4月)的学习成果 2.在本月/季度的学习过程中遇到的难题有哪些,是如何解决的,从中学到了什么? 3.有什么事情是自己一直想做 ...

  5. 第一篇博客,开启我的编程学习生涯

    目录: 一.自我介绍 二.编程的目标 三.打算怎么学编程 四.准备花费多长时间在编程上 五.目标的公司 六.结束 正文: 一.自我介绍 大家好,我是大三的学生,现在开始全力准备秋招,为了能在秋招时找到 ...

  6. 决策树经典算法ID3——我的第一篇博客

    简介 决策树是机器学习中一种常见的分类算法,属于有监督学习算法(至于什么是有监督学习,什么是无监督学习读者可以自行百度).决策树算法有多种,ID3算法是其中一种经典的决策树算法,这种算法的核心是信息熵 ...

  7. 成就小我,从第一篇博客开始

    自我介绍 你们好,这是我的第一篇博客,一起见证一个菜鸟的成长吧.作为一名物联网专业的大二学生,即将面临大三找实习的压力,前路的未知更让我感到压抑.之前一直想写博客,但由于时间关系,或是更多由于自己的惰 ...

  8. 播种:人生第一篇博客

    播种:人生第一篇博客 前言 一.自我介绍 二.未来小目标 三.学习编程计划 四.致自己 五.结语 前言 此篇为开始的见证,谨记自己的初心 自我介绍 高考结束后再三考虑还是加入这个很有"前景& ...

  9. 蒟蒻的第一篇博客CF1041C Coffee Break(二分+贪心+set)

    CF1041C Coffee Break(二分+贪心+set) 描述 Recently Monocarp got a job. His working day lasts exactly mm min ...

最新文章

  1. 【每日随笔】使用 you-get 获取网页中的视频资源 ( Python 环境安装 | you-get 工具使用 )
  2. 课外扩展:使用RADIUS来集中管理***服务器(2)
  3. spring boot自动配置之jdbc
  4. php中strtotime的意思,php中strtotime函数用法详解
  5. 【CodeForces - 255C】Almost Arithmetical Progression (dp,离散化)
  6. 打造一个实际的全系统污点分析系统--Towards Practical Taint Tracking
  7. python 学习笔记(6)-转载
  8. PDF转换技巧之如何把文件转换为WPS?
  9. [鸟哥linux视频教程整理]03_03_bash特性详解续
  10. Hive数据分析实战
  11. 两个小的java程序,用于练习java基本语法
  12. java B2B2C 多租户电子商城系统-SpringCloud动态刷新配置信息
  13. Jupyter Notebook介绍
  14. oracle基础语法(二)ORACLE查询
  15. 部分UCI数据集分享
  16. Web Fonts (二) OTF/TTF 转 WOFF
  17. iOS设置App的名称和简单的版本国际化与本地化
  18. 2017_11_23 学习echarts之饼状、柱状、gl(三维柱状)、map地图
  19. 《ECMAScript 6 入门教程》学习笔记Ⅰ
  20. 孙鑫java高清完整版(课件+视频)_孙鑫Java高清完整版(课件+视频) - 程序语言 - 小木虫 - 学术 科研 互动社区...

热门文章

  1. 参加计算机社团的英语作文,2016年12月英语六级考试作文范文:参加社团
  2. isis宣告网络_isis简要原理、实验和常用命令
  3. 如何把Community project导入到Aras Innovator 11R9
  4. Unity-托管代码剥离(link.xml使用)
  5. ansible-playbook role角色
  6. 字节笔试题(含答案)
  7. 深度原创丨揭开工业互联网看不见的手:从MindSphere+Mendix谈起
  8. java字符乱码问题_怎么解决java中的字符乱码问题
  9. Postman返回乱码问题解决
  10. magic-api项目的打包发布