python面试题(一)

整理了一些python面试可能遇到的题,提供给大家,希望能对大家有用!

1.下面的代码会输出什么?

def extend_list(val, list=[]):
    list.append(val)
    return list

list1 = extend_list(10)
list2 = extend_list(123,[])
list3 = extend_list('a')

print(list1)
print(list2)
print(list3)

extend_list函数有两个参数,val和默认参数list,返回值为list

如果你认为输出的值为:[10],[123],[a];那你就上当了,这正是出题者想让你犯的错误。

正确答案是:[10, a],[123],[10, a];为什么呢?

关键点就在extend_list返回的值,它返回的是一个变量,绑定在一个固定的地址,list3传参之后改变了list,所以最后打印的时候,list1和list3的值相同。

那么为什么list2没变呢?因为list2传参的时候给传入了一个空的列表,list2所对应的list所绑定的地址发生了改变。

如果这样说你还不清楚的话,那么我借助代码来看一看。

def extend_list(val, list=[]):
    list.append(val)
    return list


list1 = extend_list(10)
print(list1)  # [10]
print(id(list1))  # 140427568644424
list2 = extend_list(123, [])
print(list2)  # [123]
print(id(list2))  # 140427568644360
list3 = extend_list('a')
print(list3)  # [10, 'a']
print(id(list3))  # 140427568644424


print(list1)  # [10, 'a']
print(list2)  # [123]
print(list3)  # [10, 'a']

id(变量名) 可以查询变量所绑定的地址。

2.有一数组,从左到右渐增,从上到下渐增,给一个数字,判断它是否在这个数组中。

 arr = [[1,4,7,10,15], [2,5,8,12,19], [3,6,9,16,22],
  [10,13,14,17,24], [18,21,23,26,30]]

def getNum(num, data=None):
    while data:
        #  当data不为空,如果num大于data数组第1个元素的最后一项
        #  删除此元素,再执行此比较
        if num > data[0][-1]:
            del data[0]
            getNum(num, data=None)
        #  如果num小于此时的data数组第一个元素的最后一项
        #  那么利用zip转换矩阵,将所有元素的最后一项都删除掉
        #  然后再次用zip还原数组,回到第一步再次开始比较
        elif num < data[0][-1]:
            data = list(zip(*data))
            del data[-1]
            data = list(zip(*data))
            getNum(num, data=None)
        #  如果num不大于也不小于此时data数组第一个元素的最后一项
        #  那么num就是这一项,返回True
        else:
            return True
    #  当data为空时,num已经和原data数组比较完毕,且没有找到相同的数字
    #  返回False
    return False

#  如果是在当前文本打开,则执行print
if __name__ == '__main__':
    print(getNum(18, arr))

3.求两个数的最大公约数、最小公倍数。

这个是送分题,我们可以用最笨的办法

def maxCommon(a, b):
  # 两数的最大公因数最大为较小的数,所以我们遍历从1到较小的数
for i in range (1, b+1):
    # 如果a和b除以i余数都为0,那么i就是a和b的公因数
if a % i == 0 and b % i == 0:
      # 将i赋值给变量mx,因为i会从1到b,所以只要满足条件的i,都会对mx赋值
      # 新值会替代旧值,所以最后返回的是最大公因数
      mx
= i return mx


print(maxCommon(36, 21)) # 3

这种笨办法我们称之为“穷举法”,既然有笨办法,那就有聪明的办法!

接下来我们就来看聪名的办法:欧几里得算法(碾转相除法),叫欧几里得算法显得高大上,碾转相除法贴切的多。

def modUntil(a, b):
    while b:
    # 循环,序列赋值 a, b
= b, a%b return a print(modUntil(36, 21)) # 3

这是什么鬼?代码怎么可以这么简洁?怎么就循环一直除一直除就可以得到最大公因数了?还除的是余数?

容老夫给你娓娓道来。

假设x,y有一最大公因数z,x和y都可以被z整除,那么对任意整数m和n,mx+ny也可以被z整除。

现在有x / y = q 余数为 w,那么x = qy + w,可知 x -qy = w,结合上一行可知 w 可以被z整除,也就是说,x除以y的余数可以被他俩的最大公因数整除。

循环到最后,a的值为上一循环时的余数,b的值为0。

是不是涨见识了?在欧几里得算法的基础上,有没有受到启发,有没有想到其它算法?

不吹不黑,我没想到,你如果想到了,那么你牛笔了。。。。

我们再来看下一种算法:尼考曼彻斯法(碾转相减法、更相减损术),如果你想到的也是这种算法,那么恭喜你,你的思维可以和尼考曼彻斯比肩了。

def deUntil(a, b):
    while a != b:
        if a > b:
            a = a - b
        else:
            b = b - a
    return b

不会又一脸懵逼了吧?碾转相除的道理还记得吗?两者一个道理,既然能除就能减,多减几次,剩下的等同于余数。。。

最大公约数的算法会了,那么最小公倍数就简单了

将两个数相乘再除以最大公约数就是最小公倍数,这里就不做演示了。

原文地址:https://www.cnblogs.com/jiangchunyu/p/9806833.html