字节夏令营在线笔试题目

三道选择题
1.cos(nx)可以写作若干ancos(x)^n相加的形式,求cos(2048x)的a0
取x = pi/2 于是cos(x) = 0
于是有 a0 = cos(2048
pi/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时需要多少次

四、四道算法题

  1. N个边,N<10000 从中可以构成最多多少个三角形? 边不可以重复使用
    没啥好的思路

  2. 每天固定生产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完全确定才可以判断。可以先确定那些待解密的倒数第一位上字母的映射,然后先判断末位是否能满足要求,然后再确定倒数第二位。。。这样可以大量减枝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值