面试题汇总(一)

1.有一个整数列表,对于每个键值,计算除它自己以外的其他的数的乘积,编写一个函数,get_product_at_index(),输入一个整数数组并返回一个乘积列表。例如,给你:[1, 7, 3, 4],你将获得返回:[84, 13, 28, 21],因为[7* 3 *4, 1 * 3 * 4, 1 * 7 * 4, 1 * 7 * 3]

# 不使用除法
def get_product_at_index(nums):
   output = []
   out = 1
   for i in range(len(nums)):
       if i == 0:
           output.append(1)
       else:
           out = out * nums[i-1]
           output.append(out)
   middle = 1
   for i in range(len(nums)-1, -1, -1):
       output[i] = output[i] * middle
       middle = middle * nums[i]
   return output

# 使用除法
def abc(nums):
   a = 1
   for i in nums:
       a*=i
   output = [int(a/i) for i in nums]
   return output

2.假如你知道明天久其公司的股票情况,股票的价格通过一个整数数组提供,表示的是每个时间段的股价。请编写一个程序,计算当只进行一次买入和卖出股票操作,能够获得最大利益。

例如:

stork_price = [10, 7, 5, 8, 11, 9]

get_max_profit(stork_price)

你将获得返回:6

因为你在5元的时候买入,在11元的时候卖出

注意,你必须先买入之后才能卖出。而且你不能再同一时间买入卖出操作

def maxProfit(prices):
   if not prices:
       return 0
   len_prices = len(prices)
   buy1, sell1, buy2, sell2 = -prices[0], 0, -prices[0], 0
   

   for i in range(1, len_prices):
       buy1 = max(buy1, -prices[i])
       sell1 = max(sell1, buy1 + prices[i])
       buy2 = max(buy2, sell1 - prices[i])
       sell2 = max(sell2, buy2 + prices[i])
   return sell2

3.假设存在个已知列表aDict,由整数映射组成,编写一个函数,返回一个KeyList,List中的Key在aDict中映射Value为唯一值。返回的List应按递增顺序排序。

例如aDict = {

1 : 'a',

2 : 'a',

3 : 'c'

}

uniqueValues(aDict) = [3]

 

def a(dict):
   result = []
   for key in dict.keys():
       result.append(key)
       result.append(dict[key])
   return result

 

4.使用递归,实现符合以下规范的功能:

max_val((5, [1, 2], [[1, 3, 2, 4], 1])) return 5

max_val([5, [1, 2], [[1],[9]]]) return 9

def max_value(ls, rs):
   for l in ls:
       if type(l) == list:
           rs = max_value(l, rs)
           continue
       if l > rs:
           rs = l
   return rs

# 调用
max_value((5, [1, 2], [[1, 3, 2, 4], 1]), 0)

 

5.手写冒泡排序

a = [1, 34432, 54, 6, 56, 54, 7, 65, 7, 58, 76, 8, 67, 8, 35, 32, 5432, 4, 32, 432, 0]
for i in range(len(a) - 1):
   flag = 0
   for j in range(len(a) - 1 - i):
       flag = 1
       if a[j] > a[j + 1]:
           a[j], a[j + 1] = a[j + 1], a[j]
   if flag == 0:
       break

 

6.写出代码的输出结果

def f1(a):
   a = 1
def f2(a):
   a = [10]
def f3(a):
   a.append(2)
aa = 0
f1(aa)
print(aa)   # 输出结果为:0
bb = [1]
f2(bb)
print(bb)   # 输出结果为:[1]
cc = [1]
f3(cc)
print(cc)   # 输出结果为:[1,2]

7、写出代码的输出结果

alist = [1, 2, 3, ['a', 'b']]
b = alist
alist[3].append('c')
print(alist) #输出结果为:[1, 2, 3, ['a', 'b', 'c']]
print(b)     #输出结果为:[1, 2, 3, ['a', 'b', 'c']]

8、写出代码的输出结果

import copy

alist = [1, 2, 3, ['a', 'b']]
c = copy.copy(alist)
alist.append(4)
alist[3].append('c')
print(c)   #输出结果为:[1, 2, 3, ['a', 'b', 'c']]
print(alist)    #输出结果为:[1, 2, 3, ['a', 'b', 'c'], 4]

9、写出代码的输出结果

import copy

alist = [1, 2, 3, ['a', 'b', 'c']]
c = copy.deepcopy(alist)
alist.append(4)
alist[3].append('d')
print(c) #输出结果为:[1, 2, 3, ['a', 'b', 'c']]
print(alist)     #输出结果为:[1, 2, 3, ['a', 'b', 'c', 'd'], 4]

10、*arg和**dwarg作为参数的区别

# 在python中,这两个是python中的可变参数,*arg表示任意多个无名参数,类型为tuple,**kwargs表示关键字参数,为dict

11、filter、map、reduce函数的作用,每个举一例

filter(function, sequence):对sequence中的item依次执行function(item),将执行结果为True的item组成一个List/String/Tuple(取决于sequence的类型)。 filter(function or None, sequence) -> list, tuple, or string:入参为函数和列表/元组/字符串,返回值为item列表/元组/字符串。 map(function, sequence) :对sequence中的item依次执行function(item),将执行结果function(item)组成一个List返回。 map(function, sequence[, sequence, ...]) -> list:入参是为函数和列表/元组/字符串,返回值为function(item)列表。 reduce(function, sequence, starting_value):对sequence中的item顺序迭代调用function,如果有starting_value,还可以作为初始值调用。function接收的参数个数只能为2,先把sequence中第一个值和第二个值当参数传给function,再把function的返回值和第三个值当参数传给function,然后只返回一个结果。 reduce(function, sequence[, initial]) -> value:入参是为函数和列表/元组/字符串和初始值,返回值为数值。

#2.filter用法:返回执行结果为TRUE的入参(入参是列表字符元组)
print filter(lambda x:x*x-4,range(10))
#结果:[0, 1, 3, 4, 5, 6, 7, 8, 9]

#3.map的用法:对列表入参依次执行函数。入参为列表,有多少个列表,就应该有多少个入参。
print map(lambda x:x*x-4,range(10))
#结果:[-4, -3, 0, 5, 12, 21, 32, 45, 60, 77]
print map(lambda x,y:x*y-4,range(3),[8,9,10])
#结果:[-4, 5, 16]

#4.reduce用法:先把sequence中第一个值和第二个值当参数传给function,再把function的返回值和第三个值当参数传给fuction,最终返回一个结果值
#接收的入参个数只能为2
print reduce(lambda x,y:x*y-4,range(4))
#结果:-40
#计算0到100的和
print reduce(lambda x,y:x+y, range(101))
#结果:5050
print reduce(lambda x,y:x+y, range(101),100)
#结果:5150

12、写一个父类和子类,有初始化函数,有销毁函数,有子类继承父类的函数即可

class Pre:
   def __init__(self,name,sex):
   self.name = name
   self.sex = sex
       
   def __del__(self):
       print('对象:{}已被删除'.format(self.name))

       
class Stu(Pre):
   def __init__(self, name, sex, age):
       super().__init__(name, sex)
       self.age = age

13、班级表class(id,name),学生表student(id,name,classid,score)

(1) 写SQL语句创建表

CREATE TABLE `class` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`classid` int(11) NOT NULL,
`score` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `keys()` (`classid`),
CONSTRAINT `keys()` FOREIGN KEY (`classid`) REFERENCES `class` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);

(2)写SQL语句,插入2个班级,2个学生

INSERT INTO class VALUES(1, 1001),(2, 1002);
INSERT INTO student VALUES(1, '张三', 1, 100),(2, "李四", 2, 99);

(3)写SQL语句:分组查询每个班级的平均分,并按降序排序,输出,班级编号,班级名,平均分数

SELECT class.id,class.name,avg(student.score) FROM class,student WHERE class.id=student.classid GROUP BY class.id;

###Sqlalchemy的ORM相关

(1) 用Sqlalchemy写出多条件查询(A=1 and B=2) or (C=3)代码

from django.db.models import Q

Sqlalchemy.objects.filter((Q(A=1) & Q(B=2)) | Q(C=3))

(2)用Sqlalchemy写出table1和table2表关联, 并且有条件table1.A=table2.B代码

models.ForeignKey(table2, models.CASCADE)

 

 

14、@classmethod,@staticmethod有什么区别?什么情况下用@classmethod,什么情况下用@staticmethod?

  • @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。

  • @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。

 

15、dict的items() 方法与iteritems() 方法的不同?

字典的items方法作用:是可以将字典中的所有项,以列表方式返回。因为字典是无序的,所以用items方法返回字典的所有项,也是没有顺序的。

字典的iteritems方法作用:与items方法相比作用大致相同,只是它的返回值不是列表,而是一个迭代器。

(1)在Python2.x中,iteritems() 用于返回本身字典列表操作后的迭代器【Returns an iterator on all items(key/value pairs) 】,不占用额外的内存。

(2)在Python 3.x 里面,iteritems()方法已经废除了。在3.x里用 items()替换iteritems() ,可以用于 for 来循环遍历。

 

16、什么是lambda函数?下面这段代码输出是什么?

nums = range(2,20)
for i in nums:
   nums = filter(lambda x:x==i or x % i, nums)
print(nums)
# <filter object at 0x00000163EA643EB8>
(一)什么是lambda函数:

Python支持一种有趣的语法,它允许你快速定义单行的最小函数。这些叫做lambda的函数是从Lisp中借用来的,可以被用在任何需要函数的地方。

lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的匿名函数。 (注意:lambda 函数不能包含命令,它们所包含的表达式也不能超过一个)

(二)使用lambda函数的好处:

1、lambda函数比较轻便,即用即扔,很适合需要完成某一项简单功能,但是这个简单的功能只在此一处使用,连名字都很随意的情况下;

2、lambda是匿名函数,一般用来给filter,map,reduce这样的函数式编程服务;(具体使用请参考本人的上一篇博文:https://blog.csdn.net/little_fire/article/details/80498767

3、作为回调函数,可以传递给某些应用,比如消息处理等。

 

思考题:

1、对于多线程编程的理解,对于CPU密集型和IO密集型怎样使用多线程,说说线程池,线程锁的用法。

一)、对于多线程编程的理解:

  1. 简单区分程序、进程和线程

程序是指一段静态的代码

进程是指正在执行的程序,将静态的代码运行起来

线程是指正在执行程序的小单元


  1. 理解进程

理解线程之前,先简单理解一下进程。进程的三大特征:独立性、动态性、并发性。

独立性:指进程是系统中独立存在的实体,拥有独立的资源(eg:私有的地址空间)。

动态性:这是相对于程序而言的,程序是一段静态的代码,而进程是活动的,拥有自己的生命周期。

并发性:多个进程可以在单个处理器上并发执行,互不影响。

还是上面那栗子,这个班级就是一个进程,他是一个整体,他拥有自己的教室,有自己的班级名字,这里可以体现出独立性。这个班级的全体人员按照的任务清单干活,直至把教室打扫干净(即完成任务),这里可以体现出动态性。并发性呢,首先这个班级不只有一个,还有好多其他的班级,他们也可以打扫他们自己的教室,互不影响。


  1. 理解线程

线程是进程的执行单元,在程序中,线程是独立的、并发的执行流。

线程的特点:

  1. 每个线程有自己的堆栈,自己程序计数器,自己的局部变量,这里体现了线程的独立性。

  2. 相同父进程下的所有线程共享进程独立的内存单元(eg:代码段、进程的共有数据),为此可以实现线程间的相互通信。

  3. 多个线程之间也可以并发执行,互不影响。


  1. 多线程 VS 多进程

  2. 线程之间可以共享内存,而进程之间不可以。

  3. 系统创建线程代价比较小,而且多线程是实现多任务并发比多进程的效率更高。

二)、CPU密集型和IO密集型怎样使用多线程

一个计算为主的程序(专业一点称为CPU密集型程序)。多线程跑的时候,可以充分利用起所有的cpu核心,比如说4个核心的cpu,开4个线程的时候,可以同时跑4个线程的运算任务,此时是最大效率。

但是如果线程远远超出cpu核心数量 反而会使得任务效率下降,因为频繁的切换线程也是要消耗时间的。

因此对于cpu密集型的任务来说,线程数等于cpu数是最好的了。

如果是一个磁盘或网络为主的程序(IO密集型)。一个线程处在IO等待的时候,另一个线程还可以在CPU里面跑,有时候CPU闲着没事干,所有的线程都在等着IO,这时候他们就是同时的了,而单线程的话此时还是在一个一个等待的。我们都知道IO的速度比起CPU来是慢到令人发指的。所以开多线程,比方说多线程网络传输,多线程往不同的目录写文件,等等。

此时 线程数等于IO任务数是最佳的。

三)、线程池,线程锁的用法

 

2、如果有一个订单系统,包含订单信息,商品信息,价格信息,并且要维护一些状态,在设计系统时,你会提供哪些建议?

 

3、秒杀程序设计,大并发下如何不会超卖?

一):加入队列,集中处理

二):

前端页面静态化,禁止重复提交

  • 页面静态化:将前端可以静态的资源静态化。

  • 禁止重复提交:秒杀开始之后,可以对用户点击后响应前按钮置灰。

后端可拓展,缓存,限流,削峰,异步处理

  • 可拓展:服务的可扩展,可以水平添加机器将用户请求分担到不同的机器上去。数据库可扩展,支持分库分表,对于用户的请求,映射到不同的数据库,减少单台数据库的压力。

  • 内存缓存:参加秒杀系统的商品是事先可知的,可以将参加秒杀的商品信息事先缓存到redis等缓存系统中,这样可以大大的提高系统的吞吐量,减少关系型数据库的读写压力。

  • 限流: 一单秒杀开始,实际秒杀成功的用户只是库存的数量,在库存没有之后,将前端的秒杀入口关闭。

  • 削峰:数据库削峰。对于秒杀系统瞬时会有大量用户涌入,所以在抢购一开始会有很高的瞬间峰值。对于关系型数据库而言,这个是致命的,是压垮系统很重要的原因,所以如何把瞬间的高流量变成一段时间平稳的流量也是设计秒杀系统很重要的思路。实现削峰的常用的方法有利用缓存和消息中间件等技术。

  • 异步处理:秒杀系统是一个高并发系统,采用异步处理模式可以极大地提高系统并发量,其实异步处理就是削峰的一种实现方式。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2019-08-22 11:26  陈文鑫  阅读(292)  评论(0编辑  收藏  举报