python经典面试题收录

闲来无事,碰到很多python的疑难杂症,觉得应该该这些问题整理起来,以来是对自己知识能力的检测,而来方便其他朋友,所以这篇文章会不断地被更新。总的来说,这些问题其实一点都不难,能解释清楚的东西,都不能算作是是难吧。

第一题,行列式转换

1
2
3
4
5
6
7
8
9
10
#已知有一个二维列表(每一行的元素个数相同),写出函数对其行列转换并输出,比如:
a = [[1,1,1,1],
[2,2,2,2]]
#输出:
[
[1,2],
[1,2],
[1,2],
[1,2]
]

常规解法 按照常规解法,这道题需要编写两层循环,分别添加提取数组中的内容放入新数组:

解题思路一:
已经知道数组A是m*n的二维数组,那么输出必然是n*m,所以首先用生成器表达式生成了这样的数据结构(数组B),然后要做的事情就是让B[row,col] = A[col, row]

1
2
3
4
5
6
def transpose(list_a):
temp = [ [[0] for y in range(len(list_a))] for x in range(len(list_a[0])) ]
for row in range(len(list_a[0])):
for col in range(len(list_a)):
temp[row][col] = list_a[col][row]
return temp

解题思路二:
和思路一大同小异,只不过是再循环中创建一个数组,这个数组用于存储B的每一行,然后把这个数组依次加入B。

1
2
3
4
5
6
7
8
def transpose2(list_a):
result = []
for x in range(len(list_a[0])):
tmp = []
for y in range(len(list_a)):
tmp.append(list_a[y][x])
result.append(tmp)
print result

充分利用python语言特性的解法

解题思路三:
求解这道题的关键在于对zip函数函数的理解,zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。但是为了保持数据的一致性,我们最好还是把元组转成list。

1
2
def tranpose2(list_a):
return [ list(a) for a in zip(*list_a)]

第二题:写一个支持参数的装饰器

这个题比较简单了,直接参考python cook book元编程那一章,在这里就编写一个测量函数执行时间的装饰器函数吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import time
from functools import wraps

def timethis(func):
'''
计算被装饰函数的执行时长
'''
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end-start)
return result
return wrapper

在上面的 wrapper() 函数中, 装饰器内部定义了一个使用 *args 和 **kwargs 来接受任意参数的函数。 在这个函数里面调用了原始函数并将其结果返回,不过你还可以添加其他额外的代码(比如计时)。 然后这个新的函数包装器被作为结果返回来代替原始函数。

需要强调的是装饰器并不会修改原始函数的参数签名以及返回值。 使用 *args**kwargs 目的就是确保任何参数都能适用。 而返回结果值基本都是调用原始函数 func(*args, **kwargs) 的返回结果,其中func就是原始函数。

第三题:编码实现range函数

首先分析一波range函数,range函数接受三个参数,默认情况下接收一个参数表示范围,默认从零开始,默认步长为1,同时支持下降,递减,下面是简单的实现,做了大量的判断,代码看上去并不怎么美观:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def irange(*args):
try:
args = [int(x) for x in args]
except:
print('cannot only range int liked type')
return
args_count = len(args)
result = []
if args_count == 0:
print('range expected 1 arguments, got 0')
return
if args_count > 3:
print('range expected at most 3 arguments, got {}'.format(len(args)))
return
if args_count == 3:
start,end,step = args
if step < 0 and start < end:
return []
if step < 0 and start > end:
x = start
while x > end:
result.append(x)
x += step
return result
if step > 0 and start > end:
return[]
if step == 0:
print("step cannot be 0")
elif args_count == 2:
start,end = args
step = 1
else:
end = args[0]
start = 0
step = 1

x = start
while x < end:
result.append(x)
x += step
return result

第四题:求解约瑟夫环问题

有n个人围成一圈,从1开始按顺序编号,从第一个人开始从1到k(假设k=3)报数,报到k的人退出圈子,然后圈子缩小,从下一个人继续游戏,问最后留下的是原来的第几号。

解题思路:因为是循环报数,所以假设每一次报数都从数组的第一个元素开始,要保证这样,那就必须把报过数的人移动到数组的尾部,顺带删除数字的第k个元素,直到数组的长度变为1:。

1
2
3
4
5
6
7
8
9
def find_last1(lst, k):
t_lst = lst[:]
while len(t_lst) > 1:
for i in range(k-1):
#如果k为3,这个时候就把第1第2个人放到了尾部
t_lst.append(t_lst.pop(0))
#移除第3个人
t_lst.pop(0)
return t_lst[0]

还有一种方法是,直接使用python里的itertools.cycle:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from itertools import cycle
def find_last2(lst, k):
t_lst = lst[:]

while len(t_lst)>1:
#创建cycle对象
c = cycle(t_lst)
#从1到k报数
for i in range(k):
t = next(c)
#一个人出局,圈子缩小
index = t_lst.index(t)
t_lst = t_lst[index+1:] + t_lst[:index]

#游戏结束
return t_lst[0]

文章目录
  1. 1. 第一题,行列式转换
  2. 2. 第二题:写一个支持参数的装饰器
  3. 3. 第三题:编码实现range函数
  4. 4. 第四题:求解约瑟夫环问题