准算法工程师从30+场秋招中总结出的超强面经—C、Python与算法篇篇(含答案)
共 13550字,需浏览 28分钟
·
2021-07-04 21:50
极市导读
作者灯会为21届中部985研究生,七月份将入职某互联网大厂cv算法工程师。在去年灰飞烟灭的算法求职季中,经过几十场不同公司以及不同部门的面试中积累出了CV总复习系列,此为C、Python与算法篇。 >>加入极市CV技术交流群,走在计算机视觉的最前沿
算法
1.数组和链表的区别
数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。
链表是一种上一个元素的引用指向下一个元素的存储结构,链表通过指针来连接元素与元素;
(1)数组是连续存储的,链表是散列存储的。数组随机访问性强(通过下标进行快速定位),所以数组的查询比链表要快,链表不能随机查找,必须从第一个开始遍历,查找效率低。(2)数组插入和删除效率低(插入和删除需要移动数据),链表插入删除速度快(因为有next指针指向其下一个节点,通过改变指针的指向可以方便的增加删除元素)
2.堆,栈,堆栈,队列
堆(heap):堆是一种经过排序的树形数据结构,每个结点都有一个值。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:堆中某个节点的值总是不大于或不小于其父节点的值,堆总是一棵完全二叉树。
栈(stack): 它是一种具有后进先出性质的数据结构,也就是说后存放的先取,先存放的后取。
堆栈本身就是栈.
队列是先进先出,有出口和入口。
3.堆和栈的区别:
①堆栈空间分配区别:1)、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;2)、堆(操作系统):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
②堆栈缓存方式区别:1)、栈使用的是一级缓存,他们通常都是被调用时处于存储空间中,调用完毕立即释放;2)、堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。
堆:内存中,存储的是引用数据类型,引用数据类型无法确定大小,堆实际上是一个在内存中使用到内存中零散空间的链表结构的存储空间,堆的大小由引用类型的大小直接决定,引用类型的大小的变化直接影响到堆的变化
栈:是内存中存储值类型的,大小为2M,超出则会报错,内存溢出
③堆栈数据结构区别:堆(数据结构):堆可以被看成是一棵树,如:堆排序;栈(数据结构):一种先进后出的数据结构。特点:先进后出
4.堆和栈的访问哪个更快
栈是编译时分配空间,而堆是动态分配(运行时分配空间),所以栈的速度快。
5.快排和堆排
快速排序:最常用的排序算法,速度通常也是最快的。时间复杂度:O(nlogn)
最坏:O(n^2) 空间复杂度:O(nlgn) 不稳定(比如 5 3 3 4 3 8 9 10 11 这个序列,在中枢元素5和3交换就会把元素3的稳定性打乱)
实现原理:快排主要是通过选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的)。依此递归,达到总体待排序序列都有序。
堆排序:堆排序是指利用堆这种数据结构进行设计的一种排序算法。堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
时间复杂度:O(n*logn)特别适用于数据量很大的场合(百万级数据)。因为快排和归并排序都是基于递归的,数据量很大的情况下容易发生堆栈溢出。排序速度略低于快排。也是一种不稳定的排序算法。
6.介绍快排,描述一下最坏的情况
时间复杂度:最好情况O(nlogn)——Partition函数每次恰好能均分序列,其递归树的深度就为.log2n.+1(.x.表示不大于x的最大整数),即仅需递归log2n次;最坏情况O(n^2),每次划分只能将序列分为一个元素与其他元素两部分,这时的快速排序退化为冒泡排序,如果用数画出来,得到的将会是一棵单斜树,也就是说所有所有的节点只有左(右)节点的树;平均时间复杂度O(nlogn)。
解释一下快排的思路,时间复杂度,稳定吗?(略,不稳定) 稳定的排序都有哪些?(插,归并,冒泡) 解释一下堆排序?(不断得维护一个最大/小堆,时间复杂度nlgn)
7.快排和堆排的优缺点和应用场景
a : 时间复杂度都是o(nlogn)b : 效率: 快排 >归并>堆排
c : 三种算法的优缺点:快排: 极端情况下排序效率很低
归并:需要额外的内存开销,堆排序: 在快的排序算法中,相对较慢, 但应用很广.
8.知道哪些排序算法 排序的空间复杂度 各种排序算法的原理
冒泡排序、简单选择、直接插入、快速排序、堆排序、希尔排序、归并排序、基数排序。
冒泡排序:每当相邻的两个数比较后发现它们的排序与排序要求相反时,就将它们互换。
快速排序:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序的元素分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。
简单选择排序:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数为止。
堆排序:堆排序是一种树形选择排序,是对直接排序的有效改进。
直接插入排序:在要排序的一组数中,假设前面(n-1)[n>=2]个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
希尔排序:先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组记录的下标相差d,对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。当增量减至1时,进行直接插入排序后,排序完成。
归并排序:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把带排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
基数排序:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
9.二叉树、平衡二叉树、完全二叉树、满二叉树
二叉树的概念:一棵二叉树是节点的一个有限集合,该集合或者为空,或者由一个根节点加上两棵左子树和右子树组成。
平衡二叉树,又称AVL树。它或者是一棵空树,或者是具有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的高度之差之差的绝对值不超过1.。
满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。
完全二叉树:叶子节点只能分布在树的倒数第1层和倒数第二层,倒数第二层的节点必须是满的,倒数第一层的节点可以不全是满的,但是所有的节点都只能集中在树的左侧。这也说明,倒数第二层的节点肯定不会出现只有右子树,没有左子树的情况。在构建完全二叉树时,插入节点一定先插入左子树,再插入右子树。
10.为什么要构造成二叉树,N叉树可不可以
二叉树是按值来保存元素,也按值来访问元素。
11.红黑树
红黑树是一种自平衡树,它也是一颗二叉树。既然能保持平衡,说明它和 AVL 树类似,在插入或者删除时肯定有调整的过程,只不过这个调整过程并不像 AVL 树那样繁琐。为何红黑树使用得比 AVL 树更多,就是因为红黑树它的调整过程迅速且简介。红黑树有以下五个特性:性质1:节点是红色或黑色
性质2:根是黑色
性质3:所有叶子都是黑色。叶子是 NIL 节点,也就是 Null 节点
性质4:如果一个节点是红的,则它的两个儿子都是黑的
性质5:从任一节点到其叶子的所有简单路径都包含相同数目的黑色节点。
12.递归有什么缺点 A:当递归层数很多的时候,容易造成内存溢出
13.遇到哈希冲突怎么办
①开放定址法:为产生冲突的地址求得一个地址序列(),其中。其中m为表的长度,而增量有三种取值方法,线性探测再散列,平方探测再散列,随即探测再散列。
②链地址法:将所有Hash地址相同的记录都链接在同一链表中,再Hash法,同时构造多个不同的Hash函数,当产生冲突时,计算另一个Hash函数地址直到不再发生冲突为止。
③建立公共溢出区:将Hash表分为基本表和溢出表,若是与基本表发生冲突,都放入溢出表。
14.跳表
跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表,跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找,跳表不仅能提高搜索性能,同时也可以提高插入和删除操作的性能。
15.动态规划和分治的区别与联系,各自适应哪些情况
动态规划:通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。
分治法的基本思想:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
共同点:二者都要求原问题具有最优子结构性质,都是将原问题分而治之,分解成若干个规模较小(小到很容易解决的程序)的子问题.然后将子问题的解合并,形成原问题的解.
不同点:分治法将分解后的子问题看成相互独立的,通过用递归来做。
动态规划将分解后的子问题理解为相互间有联系,有重叠部分,需要记忆,通常用迭代来做。
16.图的遍历方式
从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程就叫做图的遍历。根据遍历路径的不同,通常有两种遍历图的方法:深度优先遍历和广度优先遍历。它们对无向图和有向图都适用。图的遍历算法是求解图的连通性问题、拓扑排序和求关键路径等算法的基础。
C++
1.指针和引用的区别
指针指向一块内存,它的内容是内存中的地址,而引用则是某个内存的别名,它的指向不改变。
本质区别:指针有自己的一块空间(地址),而引用只是一个别名。
使用sizeof看一个指针的大小是4(64位是8),而引用是被引用对象的大小。指针可以被初始化为NULL,而引用必须被初始化且必须是一个已有对象的引用。可以有const指针,但是没有const引用。指针在使用中可以指向其他对象,但是引用还只能是一个对象的引用,不能被改变。如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏。
2.智能指针
c++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr
3.多态的作用、多态机制
接口的多种不同的实现方式即为多态。多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术。多态就是当发出一条命令时,不同的对象接收到同样的命令后所做出的动作是不同的。
机制:多态通常有两种实现方法:子类继承父类(extends)、类实现接口(implements);无论是哪种方法,其核心之处就在于对父类方法的改写或对接口方法的实现,以取得在运行时不同的执行效果。要使用多态,在声明对象时就应该遵循一条法则:声明的总是父类类型或接口类型,创建的是实际类型。
作用:多态最大的用途我认为在于对设计和架构的复用。
4.虚函数
虚函数:实现类的多态性。
定义一个函数为虚函数,不代表函数为不被实现的函数。定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。定义一个函数为纯虚函数,才代表函数没有被实现。
C++中的虚函数的作用主要是实现了多态的机制。基类定义虚函数,子类可以重写该函数;在派生类中对基类定义的虚函数进行重写时,需要在派生类中声明该方法为虚方法。
C++里调用虚函数比调用普通函数慢:普通函数快,因为地址在编译期间指定,单纯的寻址调用。虚函数调用时,首先找虚函数表,然后找偏移地址进行调用。
5.虚函数表放在哪里,虚表指针什么时候初始化
虚函数表和静态成员变量一样,存放在全局数据区.
在构造函数中进行虚表的创建和虚表指针的初始化。
6.纯虚函数(纯虚函数在子类中没有实现会不会报错:会)
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加 =0:
定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
7.虚函数和纯虚函数的区别
含有纯虚函数的类称为抽象类,只含有虚函数的类不能称为抽象类。虚函数可以直接被使用,也可以被子类重载以后以多态形式调用,而纯虚函数必须在子类中实现该函数才可使用,因为纯虚函数在基类中只有声明而没有定义。虚函数必须实现,对虚函数来说父类和子类都有各自的版本。
8.继承是什么意思?
继承是指一个对象直接使用另一对象的属性和方法。
继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有的特性基础上进行扩展,增加功能,这样产生新的类,称作是派生类。继承呈现了面向对象程序设计的层析结构,体现了由简单到复杂的认知过程。继承是类设计层次的复用。
9.C++的继承和Java继承的区别?
c++支持多重继承,java不支持多继承;
虚继承:当我们在继承方式前加virtual 关键字,进行虚继承,虚继承内存中会通过虚基类指针指向虚基类表,该表中的数据是为虚基类指针到基类的存储区域的偏移值。
虚继承:主要解决内存重复的问题,同时避免访问冲突。
10.枚举类能否继承
枚举的作用:限定“数据集”中的元素的个数(将类理解为一个集合)、即限定枚举类对象的个数。枚举类也是类,也可以有自己的成员变量,成员方法,静态方法、静态变量等,也能实现其他的接口,不能继承其他类了。
11.类中继承的方式,为什么会有这几种方式,作用是什么
public 继承:父类成员在子类中保持原有访问级别;
private 继承:父类成员在子类中变为私有成员;
protected 继承:父类中的公有成员变为保护成员,其它成员保持不变;
12.深拷贝浅拷贝区别
假设B复制了A,修改A的时候,看B是否发生变化:如果B跟着也变了,说明是浅拷贝,拿人手短!(修改堆内存中的同一个值);如果B没有改变,说明是深拷贝,自食其力!(修改堆内存中的不同的值)。
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存。
区别:深复制和浅复制最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用。浅复制 —-只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。深复制 —-在计算机中开辟了一块新的内存地址用于存放复制的对象。
13.拷贝和赋值的区别
拷贝分为:赋值,浅拷贝,深拷贝,拷贝程度一次递增;赋值:赋值就是相当于做了个软连接,所以不管你是修改了链接文联的内容还是源文件的内容,这个文件都会有所改变(相当于镜子里的自己,你动他也动).浅拷贝:只是做了部分的拷贝,何谓部分拷贝?就是在赋值的基础上减去了列表最外层的链接,其他的和赋值基本一样.深拷贝:相当于把文件复制了一份,新文件或老文件的改变都是互不相干的,完全独立于老文件。
14. int func(int *a, int *b) 和 int func(int a, int b) 的区别
一个用指针做参数,一个用自变量做参数。
15.面向对象C++的三个特性
继承:面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
多态:多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
16. C++类构造函数和析构函数
构造函数是一个特殊的公共成员函数,它在创建类对象时会自动被调用,用于构造类对象。
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
17.构造函数和析构函数的作用
构造函数的作用:用于新建对象的初始化工作。
析构函数的作用:用于在撤销对象前,完成一些清理工作,比如:释放内存等。
每当创建对象时,需要添加初始化代码时,则需要定义自己的构造函数;
而对象撤销时,需要自己添加清理工作的代码时,则需要定义自己的析构函数。
18.C++中虚析构函数的作用
虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。也就说虚析构函数使得在删除指向子类对象的基类指针时可以调用子类的析构函数达到释放子类中堆内存的目的,而防止内存泄露的。
19. C++中malloc和new的区别
1)malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
2)对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
3)因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
4)C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。
20. C++中struct和class的区别
对于成员访问权限以及继承方式,class默认都是private,struct默认是public;class可以用于表示模板类型,struct不行;一般来说,用到继承时常用class,没用到继承时则使用struct。
21. C++ static、const
Static:如果某个属性为整个类所共有,不属于任何一个具体对象,则采用 static 关键字来声明静态成员。
Const:常对象是这样的对象:它的数据成员值在对下岗的整个生存周期内不能被改变,也就是说,常对象必须进行初始化而且不能被更新!
什么时候用static:需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见。
static关键字的作用:常用来修饰变量。全局变量被static修饰后,就称之为静态全局变量;局部变量被static修饰后,就称之为静态局部变量。统称为静态变量。
22. const和#define的区别
①编译器处理方式不同:define宏是在预处理阶段展开,const常量是编译运行阶段使用。
②类型和安全检查不同:define宏没有数据类型,不做任何类型检查,仅仅是展开。const常量有具体的数据类型,在编译阶段会执行类型检查。③存储方式不同:define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。const常量会在内存中分配(可以是堆中也可以是栈中)。④代码调试不同:const常量可以进行调试的。define是不能进行调试的,因为在预编译阶段就已经替换掉了。
23.C++的栈区和堆区知道吗?(栈区是存储函数内部变量的内存区,堆区是存动态申请的内存)
24. C++里面vector、list、deque的区别
vector:vector是连续内存空间,支持高效的随机存取和尾部插入删除,对其他位置插入删除不方便,对比数组是可以自由动态增加空间。(伪动态,也是构造新一片内存空间,拷贝旧空间数据到新空间,释放旧空间)
deque:逻辑上的连续内存空间,支持高效的随机存取和头尾部双端插入删除。在中间进行插入删除也需要进行大量的数据移动。
List:双向循环链表,支持高效的插入和删除,对随机存取不方便。
如果想要高效的存取,不在乎插入和删除的效率,选用vector.
如果需要大量的删除和插入操作,不关心随机存取,选用list
如果需要高效的存取,同时在乎首尾的插入和删除,选用deque.
25.struct和union有什么区别
①共用体和结构体都是由多个不同的数据类型成员组成, 但在任何同一时刻, 共用体只存放了一个被选中的成员, 而结构体的所有成员都存在。
②对于共用体的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构体的不同成员赋值是互不影响的。
26. C++中include时如何保证不重复加载头文件
#ifndef方式、#pragma once方式
27. C++11里面auto有什么用,不给初始值可以吗
C++11中对关键字auto进行了重新定义,可以让编译器根据初始值类型自动推断变量的类型。用auto声明的变量必须初始化
28.点积和叉乘
向量的点积:向量点积是其各个分量乘积的和
几何意义:点积的结果是一个标量,等于向量大小与夹角的cos值的乘积。
叉乘:
29. C++、Java、Python的主要区别 (编译型语言和解释性语言)
编译型语言:c, c++, Delphi,java,等;解释性语言:c#, python,Ruby, javascript.
30. STL中 vector 是怎么实现的?我答了用数组实现,然后常数时间访问,内存分配。内存不够在原有基础上扩大一倍分配。
31.python和C的区别
①语言类型:Python是一种基于解释器的语言,解释器会逐行读取代码;首先将Python编译为字节码,然后由大型C程序解释。C是一种编译语言,完整的源代码将直接编译为机器代码,由CPU直接执行。
②内存管理:Python使用自动垃圾收集器进行内存管理。在C语言中,程序员必须自己进行内存管理。
③应用:Python是一种通用编程语言,一个多范式。它主要支持面向对象编程,程序编程,函数编程。C是结构化编程语言。允许使用函数,选择(if / else等),迭代(循环)。它主要用于硬件相关的应用程序。
④速度:Python编程语言因为历史原因,有一个GIL锁,导致其对多线程支持不够好,运行速度较慢;而C语言很快,C语言是比较底层的语言,运行效率上要优于Python。
⑤复杂度不一样:在Python中,不需要声明变量类型。而在C中,必须声明变量类型。Python程序更易于学习,编写和阅读。而C程序语法比Python更难。Python中的测试和调试更容易;而在C中测试和调试更难。
32.什么时候要进行动态内存申请?
当无法事先确定对象需要使用多少内存(这些对象所需的内存大小只有在程序运行的时候才能确定)时就要申请动态内存,比如维护一个动态增长的链表或树。
33.C++内存泄漏和野指针怎么解决
内存泄漏:①访问已经释放的内存②访问没有权限的内存。
野指针:指向内存被释放的内存或者没有访问权限的内存的指针。
野指针可以使用shared_ptr和weak_ptr结合使用来尽量规避,释放内存后把指针指向NULL,防止指针在后面不小心又被解引用了。
内存泄漏的解决:使用智能指针。因为智能指针可以自动删除分配的内存。
34.C++模板的作用
模板(Template)指C++程序设计设计语言中采用类型作为参数的程序设计,支持通用程序设计。通常有两种形式:函数模板和类模板;
python
1.python is和==的区别
is是用来判断两个变量引用的对象是否为同一个,==用于判断引用对象的值是否相等。可以通过id()函数查看引用对象的地址。
2.list和tuple的区别?
list是一种有序的集合,可以随时添加和删除其中的元素。tuple是一种有序列表,它和list非常相似。tuple一旦初始化就不能修改,而且没有append() insert()这些方法,可以获取元素但不能赋值变成另外的元素。
不同点:list是可更改的,所以,可以insert,pop等,但是tuple是不可更改的,所以没有增减函数,但是其余的查询len(),index()等函数都是一样的。
3. Python里面的字典的key可以用list吗?可以用tuple吗?可以用set吗?
一个对象能不能作为字典的key,就取决于其有没有__hash__方法。所以所有python自带类型中,除了list、dict、set和内部至少带有上述三种类型之一的tuple之外,其余的对象都能当key。
4.讲一下yield关键字?它的作用是啥?
yield是一个常用于python函数定义中的关键字,它的作用是返回一个可以用来迭代(for循环)的生成器,它的应用场景通常为一个需要返回一系列值的,含有循环的函数中。
5. python是解释语言还是编译语言
python 是解释型的编程语言
6. xrange与range的区别
xrange 用法与 range 完全相同,所不同的是生成的不是一个list对象,而是一个生成器。
7. Python里面的lambda表达式写一下,随便写一个
定义一个lambda表达式,求三个数的和:
9.python和java是解释语言还是编译语言
Java编译性,python解释性。
10.Python字典采用的是什么数据结构?(使用的是key-value匹配的哈希结构)
11.Python的多线程能否用来做并行计算?(不能,它有GIL锁,但可以用多进程实现并行)
12.Python中0.35/0.05等于多少?(python中/和//的区别)
" / " 表示浮点数除法,返回浮点结果;
" // " 表示整数除法,返回不大于结果的一个最大的整数
13.python传参会改变原值吗
当我们传的参数是int、字符串(string)、float、(数值型number)、元组(tuple) 时,无论函数中对其做什么操作,都不会改变函数外这个参数的值;
当传的是字典型(dictionary)、列表型(list)时,如果是重新对其进行赋值,则不会改变函数外参数的值,如果是对其进行操作,则会改变。即变量中存储的是引用 , 是指向真正内容的内存地址 , 对变量重新赋值 , 相当于修改了变量副本存储的内存地址 , 而这时的变量已经和函数体外的变量不是同一个了, 在函数体之外的变量 , 依旧存储的是原本的内存地址 , 其值自然没有发生改变 。
参考链接
如果觉得有用,就请分享到朋友圈吧!
公众号后台回复“目标检测综述”获取综述:目标检测二十年(2001-2021)~
# CV技术社群邀请函 #
备注:姓名-学校/公司-研究方向-城市(如:小极-北大-目标检测-深圳)
即可申请加入极市目标检测/图像分割/工业检测/人脸/医学影像/3D/SLAM/自动驾驶/超分辨率/姿态估计/ReID/GAN/图像增强/OCR/视频理解等技术交流群
每月大咖直播分享、真实项目需求对接、求职内推、算法竞赛、干货资讯汇总、与 10000+来自港科大、北大、清华、中科院、CMU、腾讯、百度等名校名企视觉开发者互动交流~