面试官问我用什么进行python数据分析析,我说 python,然后他笑了,这是为什么?

在你面试的时候,你会问面试官什么问题-阿里云资讯网
在你面试的时候,你会问面试官什么问题
发布时间:
更新时间:
来源:网络
上传者:用户
如何想面试官提问
&  每次在面试的时候,面试官都会在最后给面试者一些时间,让面试者来问问题。这是一个非常好的,可以按照的思路,来了解职位、企业文化、福利待遇、技术、企业状况和前景等情况,用来弥补在前面的面试过程中自己没有了解到的情况。但是呢,因为以前面试准备不太充分,所以虽然也能地问上一些问题,但是挂一漏万,在我每次面试回来后,总觉得对企业、对职位还是没有完全了解清楚,因此不能依此作出很理性的决断。去?还是不去?所以就往往依靠大概其的感觉而定。
  后来,我就总结出了一张问题表,等到让我问问题的时候,可以有针对性地提处问题,从而来进一步了解职位和企业。今天我又把它拿出来,复习复习,同时也跟大家来分享一下,看看大家还会提出哪些问题会问,顺便也取取经。
  1. 关于职位
  a) 职责和任职要求。这大概是最核心的问题,如果你的职位有清晰详细的职位描述(JD),可能这就不是个问题了。但我曾经任职的一个职位,因为没有清晰详细的职位描述,我在任职前也忽略了这一点,致使我在任职期间,感觉很别扭,总感觉这不是我当初想象中职位,是个不适合我的职位。
  b) 前任去向和原因。问这个问题的目的是看看这个职位是不是个棘手的职位,如果你的前任因为这个职位很难做,遇到了这样那样的问题而无法解决,而离开,你就要谨慎了,想想你自己是不是有能力超越你的前任。但是,如果真是这种情况,面试官往往在此问题上含糊其辞,说什么这是个新职位,或者说前任自己去开公司了等等。你的对策“刨根问底”,寄希望从细枝末节上嗅出一点味道。
  c) 上司情况(汇报对象)。我想谁也不想找个不容易伺候的。如果,面试官就是你将来的老板,你可以从他的言谈举止、行为方式上了解他的脾气、秉性,喜欢什么、看中什么、擅长什么,想想适合不适合你。别将来每天头上都顶个雷。
  d) 下属情况。如果是个管理的职位,你还得了解了解你的下属(团队)的情况,比如:人员构成(研发、测试、构架、UED等等)、学历、年龄、薪资水平等等。的工资也许面试官不会直接告诉你,但你可以这样问:贵公司5年工作经验的高软平均工资大概多少?或类似的问题,以此,大概推断出此公司工资水平在行业内的位置。如果有可能,要求跟1、2位将来可能成为你团队中的成员的人面谈一下。我曾就这样做过,这样做还可以深入了解下面我要说的技术方面的问题。
  2. 关于技术
  a) 开发语言和技术。你可能在自己的里写你会十几种语言,精通上百种技术(尽管有些你可能只会写“Hello World”),但你肯定还是倾向于运用自己熟悉的语言和技术来工作。所以最好还是问清楚。
  b) 开发平台。我本人熟悉并且喜欢Windows平台开发,如果做其他的,我会感到不舒服。所以也会问清楚。
  c) 开发工具(包括:IDE、SC、DTS、QA、Process等工具)。这个并不是个主要的问题,但是如果你有所了解,碰巧你后面还有多轮面试,你可以事先做些功课,准备准备,不至于被人问住。
  d) 系统构架。了解系统构架,一方面可以事先了解你将来要工作在什么样的构架下,另一方面,可以向面试官展现一下你更关注宏观、全局的问题,这也是作为管理者的软素质的表现。
  3. 关于
  a) 加班。有的人没结婚、没孩子,可能喜欢下班了还留在公司,如果再有加班费,那就更好了。但我问这个问题,主要目的是想看看这个企业是不是把加班当作一种常态,是不是已经成为企业文化的一部分了。把加班当理所应当的事,这样的企业恐怕我待不了。大多数面试官在此问题上,不会承认自己公司有太多加班,但一般还会说,有些情况下是要加班的,比如:XXXX。这个时候是你真正了解他们对加班看法的最佳时机。
  b) 出差。我本人上有老、下有小,不愿经常出差。不过我知道很多人喜欢出差。所以无论喜不喜欢出差,问一问还是有好处的。这条算做企业文化,有些勉强,但也没别的更好的地方归类。暂且放这吧。
  c) 考勤。工作十几年,绝大部分时间没打卡上过班。所以事先问清楚考勤制度,心理上好做个准备。这条跟企业文化还是有很大关系的。本人还是喜欢弹性工作制。
  d) 培训。企业是不是给员工不同形式、内容的培训能看出这个企业是不是以人为本,给员工提供的路径和机会,而不是只会一味地使唤人。
  e) 团队建设。我原来的公司会经常搞一些团队建设活动。比如:Team Lunch、郊游、拓展、年会等等。这也是企业文化的一种表现。只知道让我埋头苦干的企业,我想不是我理想中的企业。
  f) 同事关系。此问题一般得到的都是正面的回答。所以问不问都行。但是至少在试用期里要关注这件事情。在团结和融洽的团队内工作,心情会很不错。
  4. 关于福利待遇
  a) 薪水组成。薪水包括哪些内容,除了工资,是不是有双薪、奖金、各种补贴、股份。不要直接问月薪给多少这样的问题,这一般有HR的人会主动问你的。但你要了解薪水的组成,因为有时候,奖金、股权等其它收益可能会很大程度地弥补薪水的不足。
  b) N险一金。这在北京好像不是个问题,一般公司都比较正规。但不排除有阴损的企业。问一句不会有损失的。
  c) 休假制度。你如果不是个工作狂,最好问问这个。如果他们比国家规定的休假多不少,你可以适当降低其它方面的要求。对我至少是这样。
  d) 合同。问问工作合同跟谁签,主要目的是看看这个公司是不是外包公司。我不愿意做外包,所以每次都问问。
  5. 关于企业
  a) 年收入。以前面试过一家国际著名的在北京的研发中心研发经理的职位,经过7轮3个Manager5个Developer的面试,最终得到了研发中心老大的面试机会。他问我,你现在所在公司的年收入多少?我说不知道。又问我再前一个公司的年收入是多少?这个我幸好知道,我说07年7千多万美元,后来,到09年降到1千多万美元,他问我降这么多,你为什么没有离开那个公司?我说我对公司是很忠诚的。但显然没有使他信服。最后他对我的结论是:对自己的发展没有明确的目标。结果倒在终点线前。所以我现在面试也问企业年收入、年利润等等,如果人均企业年收入比较低,我就要好好考虑考虑它的发展前景。如果面试官是公司高管,我会再问下面这个问题。
  b) 企业的愿景和目标。如果面试官给了你一个非常好的愿景和目标,至少说明这家企业是个有思想、有抱负的企业。如果某个公司老板自己都说不好,5年后,他的企业会在哪里、会变成什么样?我看我还是不要进到这样的企业里了。
  这些问题问得时候也得因人而异、因地制宜。如果真是双向选择,多问问没什么坏处。如果只是人家在挑我,我无论如何都想进入这家企业,那你可悠着点,别把面试官问毛了。如果真是这样,后果自负噢。
本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:zixun-group@ 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。
 网站结构是SEO的基础,要搭建利于 SEO的网站结构需要了解搜索引擎(百度)的SEO规则,这里需要讨论哪种布局对搜索引擎最友好,也可以看成搜索引擎喜欢那些布局,搜索引擎制定有哪些规则。   代码优化   ① flash, asp, html各如何优化   全站flash 的站要针对网站头部进行进一步优 化,Flash 代码只需在代码外设置内页入口   asp 代码会被搜索引擎收录但是收录效...
下个星期一开始就要接手一个新的网站,整个公司就我一个人做SEO,公司网站是同城送餐网,也是我上一篇文章说到的那个公司,老板主动加我QQ,聊了1个多小时,让我过去帮忙,工资开的不低,我就想去试试。SEO就我一个,我肯定是要负责整个网站的运营了,要为提高网站的流量、排名、转化率制定个计划,下面我就说说我自己对网站的整改和计划。   网络营销和推广方法在上篇《送餐网站推广营销方案的设定》已经说过了...
相信很多医疗网站,都有过策划专题的经验。而且,随着现在医疗网站的发展来说,一个有吸引力的专题对于网站是非常有好处的,对于医疗网站来说,专题内容策划占到了很重要的地位。那么,医疗网站专题策划需要做哪些方面?针对我做过的专题,来与大家交流下。   第一,医疗网站专题策划的主题。   网络新闻专题适合于表现各种重大新闻题材,那么,对于医疗网站来说,会以一些重大事件或者是高搜索量词做一个专题。下面,...
 12月4日消息,以“创新、融合、发展”为主题的第二届中国地方与行业网站峰会将于-5日在杭州海外海国际会展中心举行,3000多名来自互联网各界的从业人士、站长、媒体与嘉宾参加了本次盛会,admin5站长网作为大会合作媒体参与了全程报道,以下是化龙巷总经理钱钰的演讲内容。&   大家好,在这里首先感谢大会的主办方阿里集团和PHPWIND给大家提供了这么好的交流和分享...
现在准备做网站大体上有两种犹豫,一种是做一个大而全的网站犹豫,另一个是选择不好细分的行业网站犹豫,不过大部分的草根站长都把目标选择在小而细的行业型的网站,具体要选择什么样的行业那就要看草根站长个人的兴趣爱好了,最好是自己对这个行业非常熟悉的,这样才能够把这个小儿细的行业网站做到专业和极致!才能够体现出网站的差异化!   那么什么是网站细分呢?简单的说就是对目标访问群体进行具体的定位,做好这一...
 其实做这个网站的初衷也就是一群有点小抱负的几个80后,聚集在一起每个人都小激动了一把,想把自己现在做的二手房做强做大,才决定成立合肥房产网,虽然开始只是兴趣使然,但直到现在大家目标都很明确,要做就坚持做到最大最强。当时大家也没管对手有多么强大,自己能否击败他们,或许就是这种“初生牛犊不怕虎”的大无畏的自信,才让我们一路走来。好像扯远了,言归正传,现在我就总结下我们的门户网站在运营时所积累一...
若您要投稿、删除文章请联系邮箱:zixun-group@,工作人员会在5个工作日内回复。
售前咨询热线
服务与支持
账号与支持
关注阿里云
International推荐这篇日记的豆列
&&&&&&&&&&&&
&(1987人关注)
&(58561人关注)
&(64759人关注)Python面试题目--汇总
时间: 20:06:13
&&&& 阅读:380
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
原文链接-/taizilongxu/interview_python
Python语言特性
1 Python的函数参数传递
看两个例子:
def fun(a):
def fun(a):
a.append(1)
所有的变量都可以理解是内存中一个对象的&引用&,或者,也可以看似c中void*的感觉。
通过id来看引用a的内存地址可以比较理解:
def fun(a):
print "func_in",id(a)
print "re-point",id(a), id(2)
# re-point 22448
print "func_out",id(a), id(1)
# func_out 22472
注:具体的值在不同电脑上运行时可能不同。
可以看到,在执行完a = 2之后,a引用中保存的值,即内存地址发生变化,由原来1对象的所在的地址变成了2这个实体对象的内存地址。
而第2个例子a引用保存的内存值就不会发生变化:
def fun(a):
print "func_in",id(a)
a.append(1)
print "func_out",id(a)
# func_out
这里记住的是类型是属于对象的,而不是变量。而对象有两种,&可更改&(mutable)与&不可更改&(immutable)对象。在中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。(这就是这个问题的重点)
当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.
如果还不明白的话,这里有更好的解释:&
2 Python中的元类(metaclass)
这个非常的不常用,但是像ORM这种复杂的结构还是会需要的,详情请看:
3 @staticmethod和@classmethod
其实有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法,如下:
def foo(x):
print "executing foo(%s)"%(x)
class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)
@classmethod
def class_foo(cls,x):
print "executing class_foo(%s,%s)"%(cls,x)
@staticmethod
def static_foo(x):
print "executing static_foo(%s)"%x
这里先理解下函数参数里面的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)来调用.
|\|实例方法|类方法|静态方法| |:--|:--|:--|:--| |a = A()|a.foo(x)|a.class_foo(x)|a.static_foo(x)| |A|不可用|A.class_foo(x)|A.static_foo(x)|
更多关于这个问题:
4 类变量和实例变量
class Person:
name="aaa"
p1=Person()
p2=Person()
p1.name="bbb"
print p1.name
print p2.name
print Person.name
类变量就是供类使用的变量,实例变量就是供实例使用的.
这里p1.name="bbb"是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,p1.name一开始是指向的类变量name="aaa",但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了.
可以看看下面的例子:
class Person:
p1=Person()
p2=Person()
p1.name.append(1)
print p1.name
print p2.name
print Person.name
5 Python自省
这个也是python彪悍的特性.
自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().
6 字典推导式
可能你见过列表推导时,却没有见过字典推导式,在2.7中才加入的:
d = {key: value for (key, value) in iterable}
7 Python中单下划线和双下划线
&&& class MyClass():
def __init__(self):
self.__superprivate = "Hello"
self._semiprivate = ", world!"
&&& mc = MyClass()
&&& print mc.__superprivate
Traceback (most recent call last):
File "&stdin&", line 1, in &module&
AttributeError: myClass instance has no attribute ‘__superprivate‘
&&& print mc._semiprivate
&&& print mc.__dict__
{‘_MyClass__superprivate‘: ‘Hello‘, ‘_semiprivate‘: ‘, world!‘}
__foo__:一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突.
_foo:一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式.
__foo:这个有真正的意义:解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名.
8 字符串格式化:%和.format
.format在许多方面看起来更便利.对于%最烦人的是它无法同时传递一个变量和元组.你可能会想下面的代码不会有什么问题:
"hi there %s" % name
但是,如果name恰好是(1,2,3),它将会抛出一个TypeError异常.为了保证它总是正确的,你必须这样做:
"hi there %s" % (name,)
# 提供一个单元素的数组而不是一个参数
但是有点丑..format就没有这些问题.你给的第二个问题也是这样,.format好看多了.
你为什么不用它?
不知道它(在读这个之前)
为了和Python2.5兼容(譬如logging库建议使用%())
9 迭代器和生成器
这个是stackoverflow里python排名第一的问题,值得一看:&
这是中文版:&
10&*args&and&**kwargs
用*args和**kwargs只是为了方便并没有强制使用它们.
当你不确定你的函数里将要传递多少参数时你可以用*args.例如,它可以传递任意数量的参数:
&&& def print_everything(*args):
for count, thing in enumerate(args):
print ‘{0}. {1}‘.format(count, thing)
&&& print_everything(‘apple‘, ‘banana‘, ‘cabbage‘)
2. cabbage
相似的,**kwargs允许你使用没有事先定义的参数名:
&&& def table_things(**kwargs):
for name, value in kwargs.items():
print ‘{0} = {1}‘.format(name, value)
&&& table_things(apple = ‘fruit‘, cabbage = ‘vegetable‘)
cabbage = vegetable
apple = fruit
你也可以混着用.命名参数首先获得参数值然后所有的其他参数都传递给*args和**kwargs.命名参数在列表的最前端.例如:
def table_things(titlestring, **kwargs)
*args和**kwargs可以同时在函数的定义中,但是*args必须在**kwargs前面.
当调用函数时你也可以用*和**语法.例如:
&&& def print_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
就像你看到的一样,它可以传递列表(或者元组)的每一项并把它们解包.注意必须与它们在函数里的参数相吻合.当然,你也可以在函数定义或者函数调用时用*.
11 面向切面编程AOP和装饰器
这个AOP一听起来有点懵,同学面阿里的时候就被问懵了...
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
这个问题比较大,推荐:&
12 鸭子类型
&当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。&
我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。
比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。
又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等.
鸭子类型在动态语言中经常使用,非常灵活,使得python不想那样专门去弄一大堆的设计模式。
13 Python中重载
函数重载主要是为了解决两个问题。
可变参数类型。
可变参数个数。
另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。
好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,python 如何处理?答案是根本不需要处理,因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。
那么对于情况 2 ,函数功能相同,但参数个数不同,python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。
好了,鉴于情况 1 跟 情况 2 都有了解决方案,python 自然就不需要函数重载了。
14 新式类和旧式类
这个面试官问了,我说了老半天,不知道他问的真正意图是什么.
这篇文章很好的介绍了新式类的特性:&
新式类很早在2.2就出现了,所以旧式类完全是兼容的问题,Python3里的类全部都是新式类.这里有一个MRO问题可以了解下(新式类是广度优先,旧式类是深度优先),&Python核心编程&里讲的也很多.
15&__new__和__init__的区别
这个__new__确实很少见到,先做了解吧.
__new__是一个静态方法,而__init__是一个实例方法.
__new__方法会返回一个创建的实例,而__init__什么都不返回.
只有在__new__返回一个cls的实例时后面的__init__才能被调用.
当创建一个新实例时调用__new__,初始化一个实例时用__init__.
ps:&__metaclass__是创建类时起作用.所以我们可以分别使用__metaclass__,__new__和__init__来分别在类创建,实例创建和实例初始化的时候做一些小手脚.
16 单例模式
这个绝对常考啊.绝对要记住1~2个方法,当时面试官是让手写的.
1 使用__new__方法
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, ‘_instance‘):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
class MyClass(Singleton):
2 共享属性
创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法.
class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
class MyClass2(Borg):
3 装饰器版本
def singleton(cls, *args, **kw):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance
@singleton
class MyClass:
4 import方法
作为python的模块是天然的单例模式
# mysingleton.py
class My_Singleton(object):
def foo(self):
my_singleton = My_Singleton()
from mysingleton import my_singleton
my_singleton.foo()
17 Python中的作用域
Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。
当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:
本地作用域(Local)&当前作用域被嵌入的本地作用域(Enclosing locals)&全局/模块作用域(Global)&内置作用域(Built-in)
18 GIL线程全局锁
线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.
解决办法就是多进程和下面的协程(协程也只是单CPU,但是能减小切换代价提升性能).
知乎被问到了,呵呵哒,跪了
简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态.
Python里最常见的yield就是协程的思想!可以查看第九个问题.
闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。
当一个内嵌函数引用其外部作作用域的变量,我们就会得到一个闭包. 总结一下,创建一个闭包必须满足以下几点:
必须有一个内嵌函数
内嵌函数必须引用外部函数中的变量
外部函数的返回值必须是内嵌函数
感觉闭包还是有难度的,几句话是说不明白的,还是查查相关资料.
重点是函数运行后并不会被撤销,就像16题的instance字典一样,当函数运行完后,instance并不被销毁,而是继续留在内存空间里.这个功能类似类里的类变量,只不过迁移到了函数上.
闭包就像个空心球一样,你知道外面和里面,但你不知道中间是什么样.
21 lambda函数
其实就是一个匿名函数,为什么叫lambda?因为和后面的函数式编程有关.
22 Python函数式编程
这个需要适当的了解一下吧,毕竟函数式编程在Python中也做了引用.
python中函数式编程支持:
filter 函数的功能相当于过滤器。调用一个布尔函数bool_func来迭代遍历每个seq中的元素;返回一个使bool_seq返回值为true的元素的序列。
&&&a = [1,2,3,4,5,6,7]
&&&b = filter(lambda x: x & 5, a)
&&&print b
map函数是对一个序列的每个项依次执行函数,下面是对一个序列每个项都乘以2:
&&& a = map(lambda x:x*2,[1,2,3])
&&& list(a)
reduce函数是对一个序列的每个项迭代调用函数,下面是求3的阶乘:
&&& reduce(lambda x,y:x*y,range(1,4))
23 Python里的拷贝
引用和copy(),deepcopy()的区别
import copy
a = [1, 2, 3, 4, [‘a‘, ‘b‘]]
#赋值,传对象的引用
c = copy.copy(a)
#对象拷贝,浅拷贝
d = copy.deepcopy(a)
#对象拷贝,深拷贝
a.append(5)
#修改对象a
a[4].append(‘c‘)
#修改对象a中的[‘a‘, ‘b‘]数组对象
print ‘a = ‘, a
print ‘b = ‘, b
print ‘c = ‘, c
print ‘d = ‘, d
输出结果:
[1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘], 5]
[1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘], 5]
[1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘]]
[1, 2, 3, 4, [‘a‘, ‘b‘]]
24 Python垃圾回收机制
Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过&标记-清除&(mark and sweep)解决容器对象可能产生的循环引用问题,通过&分代回收&(generation collection)以空间换时间的方法提高垃圾回收效率。
1 引用计数
PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。
维护引用计数消耗资源
2 标记-清除机制
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。
3 分代技术
分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个&代&,垃圾收集频率随着&代&的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。
Python默认定义了三代对象集合,索引数越大,对象存活时间越长。
举例: 当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。
25 Python的List
26 Python的is
is是对比地址,==是对比值
27 read,readline和readlines
read 读取整个文件
readline 读取下一行,使用生成器方法
readlines 读取整个文件到一个迭代器以供我们遍历
28 Python2和3的区别
29 super init
super() lets you avoid referring to the base class explicitly, which can be nice. But the main advantage comes with multiple inheritance, where all sorts of fun stuff can happen. See the standard docs on super if you haven‘t already.
Note that the syntax changed in Python 3.0: you can just say super().__init__() instead of super(ChildB, self).__init__() which IMO is quite a bit nicer.
30 range and xrange
都在循环时使用,xrange内存性能更好。 for i in range(0, 20): for i in xrange(0, 20): What is the difference between range and xrange functions in Python 2.X? range creates a list, so if you do range(1, ) it creates a list in memory with 9999999 elements. xrange is a sequence object that evaluates lazily.
1 select,poll和epoll
其实所有的I/O都是轮询的方法,只不过实现的层面不同罢了.
这个问题可能有点深入了,但相信能回答出这个问题是对I/O多路复用有很好的了解了.其中tornado使用的就是epoll的.
基本上select有3个缺点:
连接数受限
查找配对速度慢
数据由内核拷贝到用户态
poll改善了第一个缺点
epoll改了三个缺点.
关于epoll的:&
2 调度算法
先来先服务(FCFS, First Come First Serve)
短作业优先(SJF, Shortest Job First)
最高优先权调度(Priority Scheduling)
时间片轮转(RR, Round Robin)
多级反馈队列调度(multilevel feedback queue scheduling)
最早截至时间优先 EDF
最低松弛度优先 LLF
程序推进顺序不当
请求和保持条件
不剥夺条件
环路等待条件
处理死锁基本方法:
预防死锁(摒弃除1以外的条件)
避免死锁(银行家算法)
检测死锁(资源分配图)
4 程序编译与链接
Bulid过程可以分解为4个步骤:预处理(Prepressing), 编译(Compilation)、汇编(Assembly)、链接(Linking)
预编译过程主要处理那些源文件中的以&#&开始的预编译指令,主要处理规则有:
将所有的&#define&删除,并展开所用的宏定义
处理所有条件预编译指令,比如&#if&、&#ifdef&、 &#elif&、&#endif&
处理&#include&预编译指令,将被包含的文件插入到该编译指令的位置,注:此过程是递归进行的
删除所有注释
添加行号和文件名标识,以便于编译时编译器产生调试用的行号信息以及用于编译时产生编译错误或警告时可显示行号
保留所有的#pragma编译器指令。
编译过程就是把预处理完的文件进行一系列的词法分析、语法分析、语义分析及优化后生成相应的汇编代码文件。这个过程是整个程序构建的核心部分。
汇编器是将汇编代码转化成机器可以执行的指令,每一条汇编语句几乎都是一条机器指令。经过编译、链接、汇编输出的文件成为目标文件(Object File)
链接的主要内容就是把各个模块之间相互引用的部分处理好,使各个模块可以正确的拼接。 链接的主要过程包块 地址和空间的分配(Address and Storage Allocation)、符号决议(Symbol Resolution)和重定位(Relocation)等步骤。
5 静态链接和动态链接
静态链接方法:静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地址确定下来 静态库的链接可以使用静态链接,动态链接库也可以使用这种方法链接导入库
动态链接方法:使用这种方式的程序并不在一开始就完成动态链接,而是直到真正调用动态库代码时,载入程序才计算(被调用的那部分)动态代码的逻辑地址,然后等到某个时候,程序又需要调用另外某块动态代码时,载入程序又去计算这部分代码的逻辑地址,所以,这种方式使程序初始化时间较短,但运行期间的性能比不上静态链接的程序
6 虚拟内存技术
虚拟存储器是指具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储系统.
7 分页和分段
分页: 用户程序的地址空间被划分成若干固定大小的区域,称为&页&,相应地,内存空间分成若干个物理块,页和块的大小相等。可将用户程序的任一页放在内存的任一块中,实现了离散分配。
分段: 将用户程序地址空间分成若干个大小不等的段,每段可以定义一组相对完整的逻辑信息。存储分配时,以段为单位,段与段在内存中可以不相邻接,也实现了离散分配。
分页与分段的主要区别
页是信息的物理单位,分页是为了实现非连续分配,以便解决内存碎片问题,或者说分页是由于系统管理的需要.段是信息的逻辑单位,它含有一组意义相对完整的信息,分段的目的是为了更好地实现共享,满足用户的需要.
页的大小固定,由系统确定,将逻辑地址划分为页号和页内地址是由机器硬件实现的.而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时根据信息的性质来划分.
分页的作业地址空间是一维的.分段的地址空间是二维的.
8 页面置换算法
最佳置换算法OPT:不可能实现
先进先出FIFO
最近最久未使用算法LRU:最近一段时间里最久没有使用过的页面予以置换.
9 边沿触发和水平触发
边缘触发是指每当状态变化时发生一个 io 事件,条件触发是只要满足条件就发生一个 io 事件
事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
2 数据库索引
聚集索引,非聚集索引,B-Tree,B+Tree,最左前缀原理
3 Redis原理
4 乐观锁和悲观锁
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。
6 MyISAM和InnoDB
MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。
InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持&行锁& ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。
1 三次握手
客户端通过向服务器端发送一个SYN来创建一个主动打开,作为三路握手的一部分。客户端把这段连接的序号设定为随机数 A。
服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK 的确认码应为 A+1,SYN/ACK 包本身又有一个随机序号 B。
最后,客户端再发送一个ACK。当服务端受到这个ACK的时候,就完成了三路握手,并进入了连接创建状态。此时包序号被设定为收到的确认号 A+1,而响应则为 B+1。
2 四次挥手
注意: 中断连接端可以是客户端,也可以是服务器端. 下面仅以客户端断开连接举例, 反之亦然.
客户端发送一个数据分段, 其中的 FIN 标记设置为1. 客户端进入 FIN-WAIT 状态. 该状态下客户端只接收数据, 不再发送数据.
服务器接收到带有 FIN = 1 的数据分段, 发送带有 ACK = 1 的剩余数据分段, 确认收到客户端发来的 FIN 信息.
服务器等到所有数据传输结束, 向客户端发送一个带有 FIN = 1 的数据分段, 并进入 CLOSE-WAIT 状态, 等待客户端发来带有 ACK = 1 的确认报文.
客户端收到服务器发来带有 FIN = 1 的报文, 返回 ACK = 1 的报文确认, 为了防止服务器端未收到需要重发, 进入 TIME-WAIT 状态. 服务器接收到报文后关闭连接. 客户端等待 2MSL 后未收到回复, 则认为服务器成功关闭, 客户端关闭连接.
地址解析协议(Address Resolution Protocol),其基本功能为透过目标设备的IP地址,查询目标的MAC地址,以保证通信的顺利进行。它是IPv4网络层必不可少的协议,不过在IPv6中已不再适用,并被邻居发现协议(NDP)所替代。
4 urllib和urllib2的区别
这个面试官确实问过,当时答的urllib2可以Post而urllib不可以.
urllib提供urlencode方法用来GET查询字符串的产生,而urllib2没有。这是为何urllib常和urllib2一起使用的原因。
urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL。这意味着,你不可以伪装你的User Agent字符串等。
5 Post和Get
get:&&post:&
6 Cookie和Session
&CookieSession
跟踪会话,也可以保存用户偏好设置或者保存用户名密码等
session技术是要使用到cookie的,之所以出现session技术,主要是为了安全。
7 apache和nginx的区别
nginx 相对 apache 的优点:
轻量级,同样起web 服务,比apache 占用更少的内存及资源
抗并发,nginx 处理请求是异步非阻塞的,支持更多的并发连接,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能
高度模块化的设计,编写模块相对简单
apache 相对nginx 的优点:
rewrite ,比nginx 的rewrite 强大
模块超多,基本想到的都可以找到
少bug ,nginx 的bug 相对较多
8 网站用户密码保存
明文hash后保存,如md5
MD5+Salt方式,这个salt可以随机
知乎使用了Bcrypy(好像)加密
9 HTTP和HTTPS
状态码定义
接收到请求,继续进程
步骤成功接收,被理解,并被接受
3xx 重定向
为了完成请求,必须采取进一步措施
4xx 客户端出错
请求包括错的顺序或不能完成
5xx 服务器出错
服务器无法完成显然有效的请求
403: Forbidden 404: Not Found
HTTPS握手,对称加密,非对称加密,TLS/SSL,RSA
10 XSRF和XSS
CSRF(Cross-site request forgery)跨站请求伪造
XSS(Cross Site Scripting)跨站脚本攻击
CSRF重点在请求,XSS重点在脚本
11 幂等 Idempotence
HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。(注意是副作用)
GET /account/123456,不会改变资源的状态,不论调用一次还是N次都没有副作用。请注意,这里强调的是一次和N次具有相同的副作用,而不是每次GET的结果相同。GET /latest-news这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的。
DELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE /article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。
POST所对应的URI并非创建的资源本身,而是资源的接收者。比如:POST /articles的语义是在/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。
PUT所对应的URI是要创建或更新的资源本身。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。
12 RESTful架构(SOAP,RPC)
SOAP(原为Simple Object Access Protocol的首字母缩写,即简单对象访问协议)是交换数据的一种协议规范,使用在Web服务(web service)中,交换带结构信息。SOAP为了简化网页服务器(Web Server)从XML数据库中提取数据时,节省去格式化页面时间,以及不同应用程序之间按照HTTP通信协议,遵从XML格式执行资料互换,使其抽象于语言实现、平台和硬件。
RPC(Remote Procedure Call Protocol)&&远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
总结:服务提供的两大流派.传统意义以方法调用为导向通称RPC。为了企业SOA,若干厂商联合推出webservice,制定了wsdl接口定义,传输soap.当互联网时代,臃肿SOA被简化为http+xml/json.但是简化出现各种混乱。以资源为导向,任何操作无非是对资源的增删改查,于是统一的REST出现了.
进化的顺序: RPC -& SOAP -& RESTful
15 CGI和WSGI
CGI是通用网关接口,是连接web服务器和应用程序的接口,用户通过CGI来获取动态数据或文件等。 CGI程序是一个独立的程序,它可以用几乎所有语言来写,包括perl,c,lua,python等等。
WSGI, Web Server Gateway Interface,是Python应用程序或框架和Web服务器之间的一种接口,WSGI的其中一个目的就是让用户可以用统一的语言(Python)编写前后端。
官方说明:
16 中间人攻击
在GFW里屡见不鲜的,呵呵.
中间人攻击(Man-in-the-middle attack,通常缩写为MITM)是指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。
17 c10k问题
所谓c10k问题,指的是服务器同时支持成千上万个客户端的问题,也就是concurrent 10 000 connection(这也是c10k这个名字的由来)。 推荐:&
Socket=Ip address+ TCP/UDP + port
19 浏览器缓存
304 Not Modified
20 HTTP1.0和HTTP1.1
请求头Host字段,一个服务器多个网站
文件断点续传
身份认证,状态管理,Cache缓存
AJAX,Asynchronous&&and XML(异步的&&和 XML), 是与在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。
unix进程间通信方式(IPC)
管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。
信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。
消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺
共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。
信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
红黑树与AVL的比较:
AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多;
红黑是用非严格的平衡来换取增删节点时候旋转次数的降低;
所以简单说,如果你的应用中,搜索的次数远远大于插入和删除,那么选择AVL,如果搜索,插入删除次数几乎差不多,应该选择RB。
1 台阶问题/斐波纳挈
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
fib = lambda n: n if n &= 2 else fib(n - 1) + fib(n - 2)
第二种记忆方法
def memo(func):
cache = {}
def wrap(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrap
def fib(i):
return fib(i-1) + fib(i-2)
第三种方法
def fib(n):
a, b = 0, 1
for _ in xrange(n):
a, b = b, a + b
2 变态台阶问题
一只青蛙一次可以跳上1级台阶,也可以跳上2级&&它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
fib = lambda n: n if n & 2 else 2 * fib(n - 1)
3 矩形覆盖
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
第2*n个矩形的覆盖方法等于第2*(n-1)加上第2*(n-2)的方法。
f = lambda n: 1 if n & 2 else f(n - 1) + f(n - 2)
4 杨氏矩阵查找
在一个m行n列二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
使用Step-wise线性搜索。
def get_value(l, r, c):
return l[r][c]
def find(l, x):
m = len(l) - 1
n = len(l[0]) - 1
while c &= 0 and r &= m:
value = get_value(l, r, c)
if value == x:
return True
elif value & x:
elif value & x:
return False
5 去除列表中的重复元素
list(set(l))
l1 = [‘b‘,‘c‘,‘d‘,‘b‘,‘c‘,‘a‘,‘a‘]
l2 = {}.fromkeys(l1).keys()
用字典并保持顺序
l1 = [‘b‘,‘c‘,‘d‘,‘b‘,‘c‘,‘a‘,‘a‘]
l2 = list(set(l1))
l2.sort(key=l1.index)
列表推导式
l1 = [‘b‘,‘c‘,‘d‘,‘b‘,‘c‘,‘a‘,‘a‘]
[l2.append(i) for i in l1 if not i in l2]
面试官提到的,先排序然后删除.
6 链表成对调换
1-&2-&3-&4转换成2-&1-&4-&3.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
# @param a ListNode
# @return a ListNode
def swapPairs(self, head):
if head != None and head.next != None:
next = head.next
head.next = self.swapPairs(next.next)
next.next = head
return next
return head
7 创建字典的方法
1 直接创建
dict = {‘name‘:‘earth‘, ‘port‘:‘80‘}
2 工厂方法
items=[(‘name‘,‘earth‘),(‘port‘,‘80‘)]
dict2=dict(items)
dict1=dict(([‘name‘,‘earth‘],[‘port‘,‘80‘]))
3 fromkeys()方法
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):
if len(l1) == 0 or len(l2) == 0:
tmp.extend(l1)
tmp.extend(l2)
return tmp
if l1[0] & l2[0]:
tmp.append(l1[0])
tmp.append(l2[0])
return _recursion_merge_sort2(l1, l2, tmp)
def recursion_merge_sort2(l1, l2):
return _recursion_merge_sort2(l1, l2, [])
def loop_merge_sort(l1, l2):
while len(l1) & 0 and len(l2) & 0:
if l1[0] & l2[0]:
tmp.append(l1[0])
tmp.append(l2[0])
tmp.extend(l1)
tmp.extend(l2)
return tmp
9 交叉链表求交点
去哪儿的面试,没做出来.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def node(l1, l2):
length1, lenth2 = 0, 0
# 求两个链表长度
while l1.next:
l1 = l1.next
length1 += 1
while l2.next:
l2 = l2.next
length2 += 1
# 长的链表先走
if length1 & lenth2:
for _ in range(length1 - length2):
l1 = l1.next
for _ in range(length2 - length1):
l2 = l2.next
while l1 and l2:
if l1.next == l2.next:
return l1.next
l1 = l1.next
l2 = l2.next
10 二分查找
def binarySearch(l, t):
low, high = 0, len(l) - 1
while low & high:
print low, high
mid = (low + high) / 2
if l[mid] & t:
high = mid
elif l[mid] & t:
low = mid + 1
return mid
return low if l[low] == t else False
if __name__ == ‘__main__‘:
l = [1, 4, 12, 45, 66, 99, 120, 444]
print binarySearch(l, 12)
print binarySearch(l, 1)
print binarySearch(l, 13)
print binarySearch(l, 444)
def qsort(seq):
if seq==[]:
pivot=seq[0]
lesser=qsort([x for x in seq[1:] if x&pivot])
greater=qsort([x for x in seq[1:] if x&=pivot])
return lesser+[pivot]+greater
if __name__==‘__main__‘:
seq=[5,6,78,9,0,-1,2,3,-65,12]
print(qsort(seq))
12 找零问题
coinChange(values, money, coinsUsed):
T[1:n]数组
#valuesCounts
钱币对应的种类数
找出来的总钱数
#coinsUsed
对应于目前钱币总数i所使用的硬币数目
for cents in range(1, money+1):
minCoins = cents
#从第一个开始到money的所有情况初始
for value in values:
if value &= cents:
temp = coinsUsed[cents - value] + 1
if temp & minCoins:
minCoins = temp
coinsUsed[cents] = minCoins
print(‘面值为:{0} 的最小硬币数目为:{1} ‘.format(cents, coinsUsed[cents]) )
if __name__ == ‘__main__‘:
values = [ 25, 21, 10, 5, 1]
money = 63
coinsUsed = {i:0 for i in range(money+1)}
coinChange(values, money, coinsUsed)
13 广度遍历和深度遍历二叉树
给定一个数组,构建二叉树,并且按层次打印这个二叉树
## 14 二叉树节点
class Node(object):
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
tree = Node(1, Node(3, Node(7, Node(0)), Node(6)), Node(2, Node(5), Node(4)))
## 15 层次遍历
def lookup(root):
stack = [root]
while stack:
current = stack.pop(0)
print current.data
if current.left:
stack.append(current.left)
if current.right:
stack.append(current.right)
## 16 深度遍历
def deep(root):
if not root:
print root.data
deep(root.left)
deep(root.right)
if __name__ == ‘__main__‘:
lookup(tree)
deep(tree)
17 前中后序遍历
深度遍历改变顺序就OK了
18 求最大树深
def maxDepth(root):
if not root:
return max(maxDepth(root.left), maxDepth(root.right)) + 1
19 求两棵树是否相同
def isSameTree(p, q):
if p == None and q == None:
return True
elif p and q :
return p.val == q.val and isSameTree(p.left,q.left) and isSameTree(p.right,q.right)
return False
20 前序中序求后序
def rebuild(pre, center):
if not pre:
cur = Node(pre[0])
index = center.index(pre[0])
cur.left = rebuild(pre[1:index + 1], center[:index])
cur.right = rebuild(pre[index + 1:], center[index + 1:])
return cur
def deep(root):
if not root:
deep(root.left)
deep(root.right)
print root.data
21 单链表逆置
class Node(object):
def __init__(self, data=None, next=None):
self.data = data
self.next = next
link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9)))))))))
def rev(link):
pre = link
cur = link.next
pre.next = None
while cur:
tmp = cur.next
cur.next = pre
return pre
root = rev(link)
while root:
print root.data
root = root.next
22 两个字符串是否是变位词
class Anagram:
@:param s1: The first string
@:param s2: The second string
@:return true or false
def Solution1(s1,s2):
alist = list(s2)
stillOK = True
while pos1 & len(s1) and stillOK:
found = False
while pos2 & len(alist) and not found:
if s1[pos1] == alist[pos2]:
found = True
pos2 = pos2 + 1
alist[pos2] = None
stillOK = False
pos1 = pos1 + 1
return stillOK
print(Solution1(‘abcd‘,‘dcba‘))
def Solution2(s1,s2):
alist1 = list(s1)
alist2 = list(s2)
alist1.sort()
alist2.sort()
matches = True
while pos & len(s1) and matches:
if alist1[pos] == alist2[pos]:
pos = pos + 1
matches = False
return matches
print(Solution2(‘abcde‘,‘edcbg‘))
def Solution3(s1,s2):
c1 = [0]*26
c2 = [0]*26
for i in range(len(s1)):
pos = ord(s1[i])-ord(‘a‘)
c1[pos] = c1[pos] + 1
for i in range(len(s2)):
pos = ord(s2[i])-ord(‘a‘)
c2[pos] = c2[pos] + 1
stillOK = True
while j&26 and stillOK:
if c1[j] == c2[j]:
stillOK = False
return stillOK
print(Solution3(‘apple‘,‘pleap‘))
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!}

我要回帖

更多关于 python 数据分析 面试 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信