【刷题】阿里20200330笔试

目录

第1题

第2题

总结


第1题

小强有n个养鸡场,第i个养鸡场初始有a[i]只小鸡。与其他养鸡场不同的是,他的养鸡场每天增加k只小鸡,小强每天结束都会在数量最多的养鸡场里卖掉一半的小鸡,假如一个养鸡场有x只鸡,则卖出后只剩下x/2(向下取整)只鸡。问m天后小强的n个养鸡场一共多少只小鸡?

  • 输入

    第一行输入三个int类型n,m,k(1 <= n,m,k <= 10^6)

    第二行输入n个正整数,表示n个养鸡场初始鸡的个数

  • 输出

    输出一个整数表示鸡的总数

  • 示例

    输入:

    3 3 100

    100 200 400

    输出:

    925

最后几分钟A了,很慌张。要点:

0 每天要选最大值 -> 数据结构使用大顶堆(优先队列)

1 不能去更新队列里面的每个数值(否则必tle),队列里每个数都与实际值相差了i*k (i为天数)

2 每天的最大值出队后 卖掉一半 入队的时候数值计算公式很关键:(max_-i*k)//2

计算公式是怎么来的呢?

出队得到假数值里的max -> 恢复到真数据 -> 减少一半 -> 再减去偏移量(恢复到假数值)

即 ( max_+i*k )//2 - k*i  变换后得到 ( max_ - i*k )//2 

画个图解释一下 【队列里每个数都与实际值相差了i*k (i为天数)】

在实现上,由于python只有小顶堆(headq/queue.PriorityQueue),所以去负数来实现选择最大值 即每次入队时取负、 ( max_ - i*k )//2 里的 - i*k  变成  + i*k

import sys
line = sys.stdin.readline().strip()
n, m, k = map(int, line.split())
line = sys.stdin.readline().strip()
a = list(map(int, line.split()))

from queue import PriorityQueue
q = PriorityQueue()
for i in a:
    q.put(-i) #入队时都取负

for i in range(1, m + 1):
    max_ = q.get()
    tmp= (max_ + k * i) // 2 #  - i*k 变成 + i*k
    q.put(tmp)

print(-sum(q.queue) + n * m * k) #队列里n个假数据都和真数据相差了m*k 

长度为n的优先队列,每次维护的复杂度是logn;一共取了m次最大值、修改堆 故时间复杂度为O(mlogn)

第2题

先暴力一手 例子能过 提交一直报错

交完之后发现是没有考虑输入数组为空的情况 导致分母会是0 不过照这次笔试的尿性 就算考虑了八成也是0分 这个题暂时没怎么想

题目描述:

总结

真是慌了神了 因为习惯是每道题先无脑暴力试水 然后两道题一直都是0分 搞得我一直以为自己哪里写错了 光输入改了好几次 最后还是例子没错但提交双0 心态崩了 

缓一缓 从暴力想到了几次优化:1使用优先队列 减少每次取max的复杂度 2不能每天都更改队列中所有数值,队列里每个数都与实际值相差了i*k 赶紧根据150=400-250写出了公式max_-(max_+i*k)//2 变换后和前面写的是一致的 最后几分钟A了 幸亏公式一找就找对了 要不然gg 与阿里无缘了 连面试都进不去 可真是太菜太丢人了

 

tips:

python中headq和queue.PriorityQueue的异同?

1 PriorityQueue保证线程安全 heapq 8星

2 PriorityQueue是对heapq的部分封装 也就是说PriorityQueue就用heapq实现的

 

参考资料:

https://www.nowcoder.com/discuss/396281?type=1

https://www.nowcoder.com/discuss/396031

https://stackoverflow.com/questions/36991716/whats-the-difference-between-heapq-and-priorityqueue-in-python

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章