三道选择题
1.cos(nx)可以写作若干ancos(x)^n相加的形式,求cos(2048x)的a0
取x = pi/2 于是cos(x) = 0
于是有 a0 = cos(2048pi/2) =cos(512*2pi)=1
2.平衡二叉树 依次加入3, 8, 9后的状态
3. 一个分页系统,不会
关于FIFO(页面淘汰算法)和LRU(最近最少使用算法)
二、一道多选题
求矩阵特征值
-1 1 0
-4 3 0
1 0 2
答案是1与2
三、一道填空题,有两个玻璃球,在一栋N层建筑中,找到最小的不会被摔破的楼层,所需要尝试的次数。
例如N=2时需要2
问N=8时需要多少次
四、四道算法题
-
N个边,N<10000 从中可以构成最多多少个三角形? 边不可以重复使用
没啥好的思路 -
每天固定生产M份吃的,每天额外生产一份所需额外成本是c1。可以把当天多余的保存下来,每份每天保存所需额外成本是c2。 但是最多保存t天,因为会过期。 现在给定d天的需求列表,给出最低额外成本。
思路:
用一个长度为t的列表rest记录前t天的剩余情况
遍历每天的需求,
A:如果当天需求小于M,则将当天剩余加入到rest中去,如果rest长度超过了t,则rest.pop(0)把t天前的那些库存丢掉。 (#注意,rest只是代表可以进行的储存,但是这些储存可能不会被用掉,所以这里是一个虚拟的概念,我们并不修改cost,直到我们真正用到库存时,才修改rest.)
B:如果当天需求大于M,则我们需要一些补充,有两种方案,利用库存或者是当天额外生产,我们需要比较这两种方式的成本。 前i天的库存的单位成本是ic2 当ic2 < c1时我们用库存,否则当天额外生产。 因此我们遍历rest[-1] rest[-2] … 如果还不能满足要求,我们额外生产所需。在此过程中更新cost。
m=5
c1=3
c2=1
t=2
needs=[1,1,2,4,10]
rest = []
cost = 0
for a in needs:
if a <= m:
rest.append(m-a)
if len(rest) > t:
rest.pop(0)
else:
cha = a - m
s = 0
while cha > 0 and s < len(rest):
index = len(rest)-1-s
if c2*(s+1) >= c1:
break
val = min(rest[index],cha)
cost += val*c2*(s+1)
cha -= val
rest[index] -= val
s+=1
if cha > 0:
cost += cha*c1
rest.append(0)
if len(rest) > t:
rest.pop(0)
print(cost)
3.有N个人初始各自不认识,arr记录了他们的魅力值。活动组织了M次交流,用cor=[(a0,b0)…]记录每次交流的两人A 与 B。
a.如果这两人是同一组的,此次交流无效
b.若A组中魅力值最低的不是A(记作A*),则A魅力值+2;若B组中魅力值最低的不是B(记作B),则B*魅力值+2;
c.将A组与B组合并,A与B的魅力值都+2
返回M次交流后,所有人中最低的魅力值
思路:并查集
每次对A,B先判断是否同组。
不同组的话,先找到各自组中最小的A与B,如果A*!=A则A*+=2;对B同理
然后A+=2 B+=2
再合并A与B的组
arr = [10,8,5,12,15]
cor = [(0,1),(1,2),(1,3),(2,3),(0,4)]
parent = [i for i in range(len(arr))]
def find_parent(index):
#找到index所属的组
if index == parent[index]:
return index
else:
parent[index] = find_parent(parent[index])
return parent[index]
def find_min(index):
#找到index组的最小值
ans = [float('inf'),-1]
for i in range(len(arr)):
if find_parent(i) == index:
if arr[i] < ans[0]:
ans = [arr[i], i]
return ans
for a, b in cor:
p_a = find_parent(a)
p_b = find_parent(b)
if p_a == p_b:
continue
else:
min_a,index_a = find_min(p_a)
if min_a != arr[a]:
arr[index_a] += 2
min_b,index_b = find_min(p_b)
if min_b != arr[b]:
arr[index_b] += 2
parent[p_b] = p_a
arr[a] += 2
arr[b] += 2
print(min(arr))
4.有M个由大小写字母构成的字符串,记作s1=[string1,…]. 有一个也是由大小写字母构成的密码记作P。 现尝试将s1与P中出现的字母与0~9进行一对一映射。映射后,s1与P都可以转为数字表示。如果sum(s1)=P,则配对成功。
请返回可以配对成功的组合中,P的最小数学表示。如果不能配对成功,返回0。 注意一个数字表示不能以0开头,除非它本身就是0.例如ABC不可能是012,但是单独的A可能是0.
思路:回溯查找
先将所有出现的字母用dic记录下来,其中P中出现的字母是在dic中靠前的。 记所有出现的字母种类为k。现在需要从0~9中跳出k个并得到一个序列sequence。这个sequence就记录了一种映射关系。然后我们需要判断这个映射能否满足要求。
s1 = ['AM','AM']
P = 'BM'
dic = []#记录所有出现的字母
head = set()#记录那些不能为0的字母开头
if len(P) > 1:
head.add(P[0])
for a in P:
if a not in dic:
dic.append(a)
for s in s1:
if len(s) > 1:
head.add(s[0])
for a in s:
if a not in dic:
dic.append(a)
def isTrue(sequence):
temp = {a:str(b) for a,b in zip(dic,sequence)}
right = ''
for a in P:
right += temp[a]
right = int(right)
left = 0
for s in s1:
t = ''
for a in s:
t+=temp[a]
left += int(t)
return left==right,right
def find(i,cur,already):
global flag, ans
if flag:
return
if i == len(dic):#已经构成了一个序列
flag,ans = isTrue(cur)
else:
for a in range(10):
if dic[i] in head and a == 0:
continue
if not already[a]:
cur.append(a)
already[a] = True
find(i+1, cur, already)
already[a] = False
cur.pop()
flag = False
ans = 0
already = [False for i in range(10)]
find(0,[],already)
print(ans)
但是超时了,我觉得应该可以剪枝操作。例如不必要等一个sequence完全确定才可以判断。可以先确定那些待解密的倒数第一位上字母的映射,然后先判断末位是否能满足要求,然后再确定倒数第二位。。。这样可以大量减枝。