关于Python的面试题原创手记

a=[]deffun(a):a.append(1)fun(a)printa#[1]所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。

通过id来看引用a的内存地址可以比较理解:

a=1deffun(a):print"func_in",id(a)#func_in41322472a=2print"re-point",id(a),id(2)#re-point4132244841322448print"func_out",id(a),id(1)#func_out4132247241322472fun(a)printa#1注:具体的值在不同电脑上运行时可能不同。

可以看到,在执行完a=2之后,a引用中保存的值,即内存地址发生变化,由原来1对象的所在的地址变成了2这个实体对象的内存地址。

而第2个例子a引用保存的内存值就不会发生变化:

a=[]deffun(a):print"func_in",id(a)#func_in53629256a.append(1)print"func_out",id(a)#func_out53629256fun(a)printa#[1]这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings,tuples,和numbers是不可更改的对象,而list,dict,set等则是可以修改的对象。(这就是这个问题的重点)

当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.

Python其实有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法,如下:

deffoo(x):print"executingfoo(%s)"%(x)classA(object):deffoo(self,x):print"executingfoo(%s,%s)"%(self,x)@classmethoddefclass_foo(cls,x):print"executingclass_foo(%s,%s)"%(cls,x)@staticmethoddefstatic_foo(x):print"executingstatic_foo(%s)"%xa=A()这里先理解下函数参数里面的self和cls.这个self和cls是对类或者实例的绑定,对于一般的函数来说我们可以这么调用foo(x),这个函数就是最常用的,它的工作跟任何东西(类,实例)无关.对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是foo(self,x),为什么要这么做呢因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的a.foo(x)(其实是foo(a,x)).类方法一样,只不过它传递的是类而不是实例,A.class_foo(x).注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好.

对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用a.static_foo(x)或者A.static_foo(x)来调用.

更多关于这个问题:

类变量:

是可在类的所有实例之间共享的值(也就是说,它们不是单独分配给每个实例的)。例如下例中,num_of_instance就是类变量,用于跟踪存在着多少个Test的实例。

实例变量:

实例化之后,每个实例单独拥有的变量。

classTest(object):num_of_instance=0def__init__(self,name):self.name=nameTest.num_of_instance+=1if__name__=='__main__':printTest.num_of_instance#0t1=Test('jack')printTest.num_of_instance#1t2=Test('lucy')printt1.name,t1.num_of_instance#jack2printt2.name,t2.num_of_instance#lucy2补充的例子

classPerson:name="aaa"p1=Person()p2=Person()p1.name="bbb"printp1.name#bbbprintp2.name#aaaprintPerson.name#aaa这里p1.name="bbb"是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,p1.name一开始是指向的类变量name="aaa",但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了.

可以看看下面的例子:

这个也是python彪悍的特性.

自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().

a=[1,2,3]b={'a':1,'b':2,'c':3}c=Trueprinttype(a),type(b),type(c)#printisinstance(a,list)#True6字典推导式可能你见过列表推导时,却没有见过字典推导式,在2.7中才加入的:

d={key:valuefor(key,value)initerable}7Python中单下划线和双下划线>>>classMyClass():...def__init__(self):...self.__superprivate="Hello"...self._semiprivate=",world!"...>>>mc=MyClass()>>>printmc.__superprivateTraceback(mostrecentcalllast):File"",line1,inAttributeError:myClassinstancehasnoattribute'__superprivate'>>>printmc._semiprivate,world!>>>printmc.__dict__{'_MyClass__superprivate':'Hello','_semiprivate':',world!'}__foo__:一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突,就是例如__init__(),__del__(),__call__()这些特殊方法

_foo:一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式.不能用frommoduleimport*导入,其他方面和公有一样访问;

__foo:这个有真正的意义:解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名,它无法直接像公有成员一样随便访问,通过对象名._类名__xxx这样的方式可以访问.

.format在许多方面看起来更便利.对于%最烦人的是它无法同时传递一个变量和元组.你可能会想下面的代码不会有什么问题:

"hithere%s"%name但是,如果name恰好是(1,2,3),它将会抛出一个TypeError异常.为了保证它总是正确的,你必须这样做:

"hithere%s"%(name,)#提供一个单元素的数组而不是一个参数但是有点丑…format就没有这些问题.你给的第二个问题也是这样,.format好看多了.

你为什么不用它

这里有个关于生成器的创建问题面试官有考:问:将列表生成式中[]改成()之后数据结构是否改变?答案:是,从列表变为生成器

>>>L=[x*xforxinrange(10)]>>>L[0,1,4,9,16,25,36,49,64,81]>>>g=(x*xforxinrange(10))>>>gat0x0000028F8B774200>通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含百万元素的列表,不仅是占用很大的内存空间,如:我们只需要访问前面的几个元素,后面大部分元素所占的空间都是浪费的。因此,没有必要创建完整的列表(节省大量内存空间)。在Python中,我们可以采用生成器:边循环,边计算的机制—>generator

用*args和**kwargs只是为了方便并没有强制使用它们.

当你不确定你的函数里将要传递多少参数时你可以用*args.例如,它可以传递任意数量的参数:

>>>defprint_everything(*args):forcount,thinginenumerate(args):...print'{0}.{1}'.format(count,thing)...>>>print_everything('apple','banana','cabbage')0.apple1.banana2.cabbage相似的,**kwargs允许你使用没有事先定义的参数名:

>>>deftable_things(**kwargs):...forname,valueinkwargs.items():...print'{0}={1}'.format(name,value)...>>>table_things(apple='fruit',cabbage='vegetable')cabbage=vegetableapple=fruit你也可以混着用.命名参数首先获得参数值然后所有的其他参数都传递给*args和**kwargs.命名参数在列表的最前端.例如:

deftable_things(titlestring,**kwargs)*args和**kwargs可以同时在函数的定义中,但是*args必须在**kwargs前面.

当调用函数时你也可以用*和**语法.例如:

>>>defprint_three_things(a,b,c):...print'a={0},b={1},c={2}'.format(a,b,c)...>>>mylist=['aardvark','baboon','cat']>>>print_three_things(*mylist)a=aardvark,b=baboon,c=cat就像你看到的一样,它可以传递列表(或者元组)的每一项并把它们解包.注意必须与它们在函数里的参数相吻合.当然,你也可以在函数定义或者函数调用时用*.

这个AOP一听起来有点懵,同学面阿里的时候就被问懵了…

装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。

比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。

又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等.

鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式。

函数重载主要是为了解决两个问题。

另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。

好吧,那么对于情况1,函数功能相同,但是参数类型不同,python如何处理?答案是根本不需要处理,因为python可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在python中很可能是相同的代码,没有必要做成两个不同函数。

那么对于情况2,函数功能相同,但参数个数不同,python如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。

好了,鉴于情况1跟情况2都有了解决方案,python自然就不需要函数重载了。

这个面试官问了,我说了老半天,不知道他问的真正意图是什么.

新式类很早在2.2就出现了,所以旧式类完全是兼容的问题,Python3里的类全部都是新式类.这里有一个MRO问题可以了解下(新式类是广度优先,旧式类是深度优先),里讲的也很多.

一个旧式类的深度优先的例子

classA():deffoo1(self):print"A"classB(A):deffoo2(self):passclassC(A):deffoo1(self):print"C"classD(B,C):passd=D()d.foo1()#A按照经典类的查找顺序从左到右深度优先的规则,在访问d.foo1()的时候,D这个类是没有的…那么往上查找,先找到B,里面没有,深度优先,访问A,找到了foo1(),所以这时候调用的是A的foo1(),从而导致C重写的foo1()被绕过

这个__new__确实很少见到,先做了解吧.

ps:__metaclass__是创建类时起作用.所以我们可以分别使用__metaclass__,__new__和__init__来分别在类创建,实例创建和实例初始化的时候做一些小手脚.

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

__new__()在__init__()之前被调用,用于生成实例对象。利用这个方法和类的属性的特点可以实现设计模式的单例模式。单例模式是指创建唯一对象,单例模式设计的类只能实例这个绝对常考啊.绝对要记住1~2个方法,当时面试官是让手写的.

classSingleton(object):def__new__(cls,*args,**kw):ifnothasattr(cls,'_instance'):orig=super(Singleton,cls)cls._instance=orig.__new__(cls,*args,**kw)returncls._instanceclassMyClass(Singleton):a=12共享属性创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法.

classBorg(object):_state={}def__new__(cls,*args,**kw):ob=super(Borg,cls).__new__(cls,*args,**kw)ob.__dict__=cls._statereturnobclassMyClass2(Borg):a=13装饰器版本defsingleton(cls):instances={}defgetinstance(*args,**kw):ifclsnotininstances:instances[cls]=cls(*args,**kw)returninstances[cls]returngetinstance@singletonclassMyClass:...4import方法作为python的模块是天然的单例模式

Python中,一个变量的作用域总是由在代码中被赋值的地方所决定的。

当Python遇到一个变量的话他会按照这样的顺序进行搜索:

本地作用域(Local)当前作用域被嵌入的本地作用域(Enclosinglocals)全局/模块作用域(Global)内置作用域(Built-in)

解决办法就是多进程和下面的协程(协程也只是单CPU,但是能减小切换代价提升性能).

知乎被问到了,呵呵哒,跪了

Python里最常见的yield就是协程的思想!可以查看第九个问题.

闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。

当一个内嵌函数引用其外部作作用域的变量,我们就会得到一个闭包.总结一下,创建一个闭包必须满足以下几点:

重点是函数运行后并不会被撤销,就像16题的instance字典一样,当函数运行完后,instance并不被销毁,而是继续留在内存空间里.这个功能类似类里的类变量,只不过迁移到了函数上.

闭包就像个空心球一样,你知道外面和里面,但你不知道中间是什么样.

其实就是一个匿名函数,为什么叫lambda因为和后面的函数式编程有关.

这个需要适当的了解一下吧,毕竟函数式编程在Python中也做了引用.

python中函数式编程支持:

filter函数的功能相当于过滤器。调用一个布尔函数bool_func来迭代遍历每个seq中的元素;返回一个使bool_seq返回值为true的元素的序列。

>>>a=[1,2,3,4,5,6,7]>>>b=filter(lambdax:x>5,a)>>>printb>>>[6,7]map函数是对一个序列的每个项依次执行函数,下面是对一个序列每个项都乘以2:

>>>a=map(lambdax:x*2,[1,2,3])>>>list(a)[2,4,6]reduce函数是对一个序列的每个项迭代调用函数,下面是求3的阶乘:

>>>reduce(lambdax,y:x*y,range(1,4))623Python里的拷贝引用和copy(),deepcopy()的区别

PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。

优点:

缺点:

基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。

is是对比地址,==是对比值

super()letsyouavoidreferringtothebaseclassexplicitly,whichcanbenice.Butthemainadvantagecomeswithmultipleinheritance,whereallsortsoffunstuffcanhappen.Seethestandarddocsonsuperifyouhaven’talready.

NotethatthesyntaxchangedinPython3.0:youcanjustsaysuper().__init__()insteadofsuper(ChildB,self).__init__()whichIMOisquiteabitnicer.

都在循环时使用,xrange内存性能更好。foriinrange(0,20):foriinxrange(0,20):WhatisthedifferencebetweenrangeandxrangefunctionsinPython2.Xrangecreatesalist,soifyoudorange(1,10000000)itcreatesalistinmemorywith9999999elements.xrangeisasequenceobjectthatevaluateslazily.

其实所有的I/O都是轮询的方法,只不过实现的层面不同罢了.

这个问题可能有点深入了,但相信能回答出这个问题是对I/O多路复用有很好的了解了.其中tornado使用的就是epoll的.

基本上select有3个缺点:

poll改善了第一个缺点

epoll改了三个缺点.

实时调度算法:

原因:

必要条件:

处理死锁基本方法:

Bulid过程可以分解为4个步骤:预处理(Prepressing),编译(Compilation)、汇编(Assembly)、链接(Linking)

以c语言为例:

预编译过程主要处理那些源文件中的以“#”开始的预编译指令,主要处理规则有:

编译过程就是把预处理完的文件进行一系列的词法分析、语法分析、语义分析及优化后生成相应的汇编代码文件。这个过程是整个程序构建的核心部分。

汇编器是将汇编代码转化成机器可以执行的指令,每一条汇编语句几乎都是一条机器指令。经过编译、链接、汇编输出的文件成为目标文件(ObjectFile)

链接的主要内容就是把各个模块之间相互引用的部分处理好,使各个模块可以正确的拼接。链接的主要过程包块地址和空间的分配(AddressandStorageAllocation)、符号决议(SymbolResolution)和重定位(Relocation)等步骤。

静态链接方法:静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地址确定下来静态库的链接可以使用静态链接,动态链接库也可以使用这种方法链接导入库

虚拟存储器是指具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储系统.

分页:用户程序的地址空间被划分成若干固定大小的区域,称为“页”,相应地,内存空间分成若干个物理块,页和块的大小相等。可将用户程序的任一页放在内存的任一块中,实现了离散分配。

分段:将用户程序地址空间分成若干个大小不等的段,每段可以定义一组相对完整的逻辑信息。存储分配时,以段为单位,段与段在内存中可以不相邻接,也实现了离散分配。

边缘触发是指每当状态变化时发生一个io事件,条件触发是只要满足条件就发生一个io事件

聚集索引,非聚集索引,B-Tree,B+Tree,最左前缀原理

通常局限点来说,Redis也以消息队列的形式存在,作为内嵌的List存在,满足实时的高并发需求。在使用缓存的时候,redis比memcached具有更多的优势,并且支持更多的数据类型,把redis当作一个中间存储系统,用来处理高并发的数据库操作

悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作

乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。

其中,写操作(insert、delete和update)执行时,需要将系统版本号递增。

由于旧数据并不真正的删除,所以必须对这些数据进行清理,innodb会开启一个后台线程执行清理工作,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫做purge。

通过MVCC很好的实现了事务的隔离性,可以达到repeatedread级别,要实现serializable还必须加锁。

MyISAM适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM对于SELECTCOUNT(*)这类的计算是超快无比的。

InnoDB的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比MyISAM还慢。他是它支持“行锁”,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。

注意:中断连接端可以是客户端,也可以是服务器端.下面仅以客户端断开连接举例,反之亦然.

地址解析协议(AddressResolutionProtocol),其基本功能为透过目标设备的IP地址,查询目标的MAC地址,以保证通信的顺利进行。它是IPv4网络层必不可少的协议,不过在IPv6中已不再适用,并被邻居发现协议(NDP)所替代。

这个面试官确实问过,当时答的urllib2可以Post而urllib不可以.

session技术是要使用到cookie的,之所以出现session技术,主要是为了安全。

nginx相对apache的优点:

apache相对nginx的优点:

403:Forbidden404:NotFound

HTTPS握手,对称加密,非对称加密,TLS/SSL,RSA

CSRF重点在请求,XSS重点在脚本

HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。(注意是副作用)

RPC(RemoteProcedureCallProtocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

进化的顺序:RPC->SOAP->RESTful

CGI是通用网关接口,是连接web服务器和应用程序的接口,用户通过CGI来获取动态数据或文件等。CGI程序是一个独立的程序,它可以用几乎所有语言来写,包括perl,c,lua,python等等。

WSGI,WebServerGatewayInterface,是Python应用程序或框架和Web服务器之间的一种接口,WSGI的其中一个目的就是让用户可以用统一的语言(Python)编写前后端。

在GFW里屡见不鲜的,呵呵.

中间人攻击(Man-in-the-middleattack,通常缩写为MITM)是指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。

Socket=Ipaddress+TCP/UDP+port

304NotModified

HTTP请求8种方法介绍HTTP/1.1协议中共定义了8种HTTP请求方法,HTTP请求方法也被叫做“请求动作”,不同的方法规定了不同的操作指定的资源方式。服务端也会根据不同的请求方法做不同的响应。

GET

GET请求会显示请求指定的资源。一般来说GET方法应该只用于数据的读取,而不应当用于会产生副作用的非幂等的操作中。

GET会方法请求指定的页面信息,并返回响应主体,GET被认为是不安全的方法,因为GET方法会被网络蜘蛛等任意的访问。

HEAD

HEAD方法与GET方法一样,都是向服务器发出指定资源的请求。但是,服务器在响应HEAD请求时不会回传资源的内容部分,即:响应主体。这样,我们可以不传输全部内容的情况下,就可以获取服务器的响应头信息。HEAD方法常被用于客户端查看服务器的性能。

POST

POST请求会向指定资源提交数据,请求服务器进行处理,如:表单数据提交、文件上传等,请求数据会被包含在请求体中。POST方法是非幂等的方法,因为这个请求可能会创建新的资源或/和修改现有资源。

PUT

PUT请求会身向指定资源位置上传其最新内容,PUT方法是幂等的方法。通过该方法客户端可以将指定资源的最新数据传送给服务器取代指定的资源的内容。

DELETE

DELETE请求用于请求服务器删除所请求URI(统一资源标识符,UniformResourceIdentifier)所标识的资源。DELETE请求后指定资源会被删除,DELETE方法也是幂等的。

CONNECT

CONNECT方法是HTTP/1.1协议预留的,能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通信。

OPTIONS

OPTIONS请求与HEAD类似,一般也是用于客户端查看服务器的性能。这个方法会请求服务器返回该资源所支持的所有HTTP请求方法,该方法会用’*’来代替资源名称,向服务器发送OPTIONS请求,可以测试服务器功能是否正常。JavaScript的XMLHttpRequest对象进行CORS跨域资源共享时,就是使用OPTIONS方法发送嗅探请求,以判断是否有对指定资源的访问权限。允许

TRACE

TRACE请求服务器回显其收到的请求信息,该方法主要用于HTTP请求的测试或诊断。

HTTP/1.1之后增加的方法

在HTTP/1.1标准制定之后,又陆续扩展了一些方法。其中使用中较多的是PATCH方法:

PATCH

PATCH方法出现的较晚,它在2010年的RFC5789标准中被定义。PATCH请求与PUT请求类似,同样用于资源的更新。二者有以下两点不同:

但PATCH一般用于资源的部分更新,而PUT一般用于资源的整体更新。当资源不存在时,PATCH会创建一个新的资源,而PUT只会对已在资源进行更新。

AJAX,AsynchronousJavaScriptandXML(异步的JavaScript和XML),是与在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。

红黑树与AVL的比较:

AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多;

红黑是用非严格的平衡来换取增删节点时候旋转次数的降低;

所以简单说,如果你的应用中,搜索的次数远远大于插入和删除,那么选择AVL,如果搜索,插入删除次数几乎差不多,应该选择RB。

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

fib=lambdan:nifn<=2elsefib(n-1)+fib(n-2)第二种记忆方法

defmemo(func):cache={}defwrap(*args):ifargsnotincache:cache[args]=func(*args)returncache[args]returnwrap@memodeffib(i):ifi<2:return1returnfib(i-1)+fib(i-2)第三种方法

deffib(n):a,b=0,1for_inxrange(n):a,b=b,a+breturnb2变态台阶问题一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

fib=lambdan:nifn<2else2*fib(n-1)3矩形覆盖我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

第2*n个矩形的覆盖方法等于第2*(n-1)加上第2*(n-2)的方法。

f=lambdan:1ifn<2elsef(n-1)+f(n-2)4杨氏矩阵查找在一个m行n列二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

使用Step-wise线性搜索。

defget_value(l,r,c):returnl[r][c]deffind(l,x):m=len(l)-1n=len(l[0])-1r=0c=nwhilec>=0andr<=m:value=get_value(l,r,c)ifvalue==x:returnTrueelifvalue>x:c=c-1elifvalue

list(set(l))用字典

l1=['b','c','d','b','c','a','a']l2={}.fromkeys(l1).keys()printl2用字典并保持顺序

l1=['b','c','d','b','c','a','a']l2=list(set(l1))l2.sort(key=l1.index)printl2列表推导式

l1=['b','c','d','b','c','a','a']l2=[][l2.append(i)foriinl1ifnotiinl2]sorted排序并且用列表推导式.

l=[‘b’,‘c’,‘d’,‘b’,‘c’,‘a’,‘a’][single.append(i)foriinsorted(l)ifinotinsingle]printsingle

1->2->3->4转换成2->1->4->3.

classListNode:def__init__(self,x):self.val=xself.next=NoneclassSolution:#@paramaListNode#@returnaListNodedefswapPairs(self,head):ifhead!=Noneandhead.next!=None:next=head.nexthead.next=self.swapPairs(next.next)next.next=headreturnnextreturnhead7创建字典的方法1直接创建dict={'name':'earth','port':'80'}2工厂方法items=[('name','earth'),('port','80')]dict2=dict(items)dict1=dict((['name','earth'],['port','80']))3fromkeys()方法dict1={}.fromkeys(('x','y'),-1)dict={'x':-1,'y':-1}dict2={}.fromkeys(('x','y'))dict2={'x':None,'y':None}8合并两个有序列表知乎远程面试要求编程

尾递归

def_recursion_merge_sort2(l1,l2,tmp):iflen(l1)==0orlen(l2)==0:tmp.extend(l1)tmp.extend(l2)returntmpelse:ifl1[0]

思路:

定义一个新的空列表

比较两个列表的首个元素

小的就插入到新列表里

把已经插入新列表的元素从旧列表删除

直到两个旧列表有一个为空

再把旧列表加到新列表后面

defloop_merge_sort(l1,l2):tmp=[]whilelen(l1)>0andlen(l2)>0:ifl1[0]

a=[1,2,3,7]b=[3,4,5]defmerge_sortedlist(a,b):c=[]whileaandb:ifa[0]>=b[0]:c.append(b.pop(0))else:c.append(a.pop(0))whilea:c.append(a.pop(0))whileb:c.append(b.pop(0))returncprintmerge_sortedlist(a,b)9交叉链表求交点其实思想可以按照从尾开始比较两个链表,如果相交,则从尾开始必然一致,只要从尾开始比较,直至不一致的地方即为交叉点,如图所示

#使用a,b两个list来模拟链表,可以看出交叉点是7这个节点a=[1,2,3,7,9,1,5]b=[4,5,7,9,1,5]foriinrange(1,min(len(a),len(b))):ifi==1and(a[-1]!=b[-1]):print"No"breakelse:ifa[-i]!=b[-i]:print"交叉节点:",a[-i+1]breakelse:pass另外一种比较正规的方法,构造链表类

classListNode:def__init__(self,x):self.val=xself.next=Nonedefnode(l1,l2):length1,lenth2=0,0#求两个链表长度whilel1.next:l1=l1.nextlength1+=1whilel2.next:l2=l2.nextlength2+=1#长的链表先走iflength1>lenth2:for_inrange(length1-length2):l1=l1.nextelse:for_inrange(length2-length1):l2=l2.nextwhilel1andl2:ifl1.next==l2.next:returnl1.nextelse:l1=l1.nextl2=l2.next修改了一下:

给定一个数组,构建二叉树,并且按层次打印这个二叉树

classNode(object):def__init__(self,data,left=None,right=None):self.data=dataself.left=leftself.right=righttree=Node(1,Node(3,Node(7,Node(0)),Node(6)),Node(2,Node(5),Node(4)))15层次遍历deflookup(root):row=[root]whilerow:print(row)row=[kidforiteminrowforkidin(item.left,item.right)ifkid]16深度遍历defdeep(root):ifnotroot:returnprintroot.datadeep(root.left)deep(root.right)if__name__=='__main__':lookup(tree)deep(tree)

THE END
1.面试题人工智能工程师高频面试题汇总:机器学习深化篇(题目+解析: Sigmoid函数在输入值远离原点时梯度非常小,容易导致梯度消失问题。 09 Leaky ReLU相比于ReLU的主要优势是什么? A. 没有梯度消失问题 B. 更快的计算速度 C. 减轻了神经元死亡问题 D. 输出范围更宽 答案: C 解析: Leaky ReLU通过在负值区域引入一个斜率,减轻了ReLU中的神经元死亡问题。 https://blog.51cto.com/u_15343919/12843670
2.Python每日一练:算法的使用指南几何级数时间复杂度:适用于汉诺塔问题。 - 阶乘时间复杂度:适用于旅行商问题,该问题属于NP完全问题。 01常用算法 穷举法,亦称暴力破解法,通过对所有可能的选项进行逐一验证,直至发现正确答案为止。 五人分鱼的案例 fish=6# 初始化鱼的数量为6 whileTrue:# 使用while True循环,表示这是一个无限循环,直到找到符合条件https://yun.zjer.cn/index.php?r=space/person/blog/view&sid=172778&id=39543787
3.算法期末考试练习题!!!伊甸一点A 子问题必须是一样的 B 子问题不能够重复 C 子问题的解可以合并 D 原问题和子问题使用相同的方法解 14.下列算法中不能解决0/1背包问题的是(A ) A 贪心法 B 动态规划 C 回溯法 D 分支限界法 15.以下( C )不能不能在线性时间完成排序 A 计数排序 B 基数排序 C 堆排序 D 桶排序 https://www.cnblogs.com/zpfbuaa/p/5087086.html
4.在线扑克如何作弊:一次软件安全研究安全IT业界软件问题是引起安全风险的一种臭名昭著的形式,而且它常常被 过分相信防火墙和加密技术的公司所忽略。软件应用程序会给一个系统带来非常多的安全漏洞,我们每天都会花大量的时间来找出并解决这些软件安全问题,所以我 们注意到在线扑克也是迟早的事。本文的其余部分就专门来讨论我们在一个流行的在线扑克游戏中发现的软件https://www.open-open.com/news/view/54e21b
5.AlphaFold3来了!全面预测蛋白质与所有生命分子相互作用及结构蛋白质设计的底层逻辑与基本规则,学习蛋白质结构预测、蛋白质序列设计、蛋白质-蛋白质相互作用分析、以及蛋白质功能注释和优化方法,掌握深度学习在蛋白质设计中的常见算法以及实际方法,培养学生具备基本的深度学习蛋白质设计能力和蛋白质人工智能应用的前沿视野,为参与解决生物医学、生物工程和生物能源等方面的重大问题提供https://cloud.tencent.com/developer/article/2437597
6.算法最接近点对问题一维在计算机科学和算法设计中,"最接近点对问题"是一个经典的几何问题,它寻找一组点集中距离最近的两个点。在这个场景下,我们关注的是在一维空间中的点对问题,也就是只考虑沿一条直线分布的点。这个问题相对简单,但仍然是理解和掌握更复杂多维最接近点对算法的基础。 在给定的描述中,提到的实现方式是通过结构体数组https://download.csdn.net/download/fishloyal/3893880
7.天花板编程手把手计划第1期第3天这个算法的特点是不需要回退。 以上两种是数据结构中的经典算法,不过我们今天要讲的并非这两种。所以千万不要被吓到了。 2.2 功能分解 首先说一下,经典的编程问题,每个都有经典的解法。这些解法是很多人共同总结出来的可以解决一类问题的最优算法。然而,对于某一个具体的问题,这些算法并不一定是最优的或者说最简单https://www.jianshu.com/p/e6d4733daca8
8.百度笔试题目及答案现在要求设计一个算法, 给定一个数k 判断出k是否在这个矩阵中。 描述算法并且给出时间复杂度(不考虑载入矩阵的消耗) 算法思想: 沿着对角线查找,获得i,使得k位于a[i][i]与a[i+1][i+1]之间。 k只可能存在于a[i][i]对应的右上角矩阵 和a[i+1][i+1]对应的左下角矩阵。 https://yjbys.com/bishi/timu/745487.html
9.力扣(LeetCode)全球极客挚爱的技术成长平台海量技术面试题库,拥有算法、数据结构、系统设计等 1000+题目,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode-cn.com/
10.高中数学新课标研读心得体会(精选13篇)无论是软件还是硬件都离不开算法的设计,算法原为计算机程序设计的组成部分,现在把它放到高中数学课本的必修部分,充分体现了新课标重应用、重能力的思想。算法严格地说是数学的一个分支,然而算法的相关概念比较枯燥,理论过于抽象,对学生的能力要求较高,所以在教学过程中往往难以把握,也不容易引起学生的兴趣,俗话说"https://www.ruiwen.com/word/gaozhongshuxuexinkebiaoyanduxindetihui.html
11.重建生态:价值与系统的力量——第七届中国教育创新年会11月启幕我们必须从这些底层的逻辑,演绎出思维的脚手架、行动的工具箱,系统的方法论,人人参与,去搭建我们重构教育、解决问题的操作支点与行动空间,并推动我们自己分析现象,理清逻辑,有效行动。 我们必须以系统的设计,生态的视野,重建教育价值,在2020这个划时代的转折时刻,展开一场严肃的讨论:教育的基础价值和根本目标,究竟是https://sghexport.shobserver.com/html/toutiao/2020/08/26/250533.html
12.福建省教育厅关于公布福建省普通高中学业水平合格性考试信息技术“算法与程序设计”模块是高中信息技术课程的选修模块,以问题解决与程序设计为主线,揭示利用计算机编程解决问题的过程。通过本模块的学习,使学生体验算法思想与方法,了解算法和程序设计在解决问题过程中的地位和作用。能从简单问题出发,设计算法,并能初步使用一种程序设计语言编制程序、实现算法、解决问题。 https://fszx.lyun.edu.cn/info/1039/1057.htm
13.索尼微单A6500评测(全文)索尼A6500数码影音评测索尼始终没有给其APS-C系列机身增加前拨轮,这可能是对相机操控感影响最为明显的一个问题,其设计采用机顶和机背的拨轮来完成操作,这也是和其他传统专业级相机在操控设计上最大的不同之一。就实际操作而言,相机的效率不至于因此降低,但的确需要适应。 https://dcdv.zol.com.cn/620/6202112_all.html
14.计算力学快讯,第8卷,第11期计算力学快讯计算力学快讯简介:本快讯是分享计算力学及相关软件信息的一个交流平台;由河海大学工程与科学数值模拟软件中心、江苏省力学学会信息服务部、中国力学学会计算力学软件专业组、南昌大学航空航天研究院联合主办;免费订阅,自由退订;欢迎各位计算力学同仁的投稿和反馈意见。 http://jsstam.org.cn/?list_73/1112.html
15.TCCT通讯Newsletter2017No.01一种基于非线性振荡器的步态轨迹自适应算法 自动化学报, 2016 Vol. 42 (12): 1951-1959 Abstract | PDF 自动化学报,2016年 第11期 目录 目录 自动化学报, 2016 Vol. 42 (11): 0-0 Abstract | PDF 论述与评论 李贤伟, 高会军 有限频域分析与设计的广义KYP引理方法综述 自动化学报, 2016 Vol. 42 (11https://tcct.amss.ac.cn/newsletter/2017/201701/journal.html
16.科学网—经典的算法回顾温故而知新,下面回顾一下经典算法:递归法、分治法、动态规划、贪心法、回溯法、分支限界法、概率算法、线性规划法、近似算法个人感觉在神经认知计算中可能需要从这里面诞生出来。 递归法 递归(Recursion)是设计和描述算法的一种有力的工具,由于它在复杂算法的描述中被经常采用。在数学与计算机科学中,是指在函数https://blog.sciencenet.cn/blog-315535-665392.html
17.算法决策:人工智能驱动的公共决策及其风险*【内容提要】作为一种自主算法决策,人工智能技术已经渗透到公共决策过程的各个环节,使公共决策模式产生重大变革。本文基于公共政策循环理论的视角,提出了一个人工智能算法对公共政策的问题界定与议程设置、政策制定、政策执行和政策评估四个阶段的影响与应用的分析框架,指出人工智能算法通过其大数据处理能力和预测分析能力,对https://www.opentimes.cn/html/Abstract/20842.html
18.优化面向智能交通的整数规划问题运筹OR帷幄拉格朗日松弛方法可应用于交通离散网络设计(DNDP)问题[2],寻找可靠路径规划问题[3],可靠设施选址问题[4]等。传统拉格朗日松弛方法应用于交通系统优化中存在对称性等问题,可通过变量分离等方法解决[5]。 3.2 交替方向乘子法 交替方向乘子法是一种结合了增广拉格朗日松弛算法和块坐标下降方法的对偶分解算法。交替方向乘子https://www.shangyexinzhi.com/article/5213211.html
19.高中信息技术课程标准各选修模块对开设条件的要求有所不同,各学校至少应开设“算法与程序设计”“多媒体技术应用”“网络技术应用”“数据管理技术”中的两个,也要制定规划,逐步克服经费、师资、场地、设备等因素的制约,开出包括“人工智能初步”在内的所有选修模块,为学生提供更丰富的选择。建议将选修模块安排在高中一年级第二学期或https://www.fqkhzx.cn/index/article/view/id/94.html