高效的队列deque
今天这一题有点烧脑:
有一个序列u,满足:
1. 第一个元素是1
2. 此后任意一个元素x,2x+1和3x+1也必定在u中
现给定整数n,求序列u中的第n+1个元素是什么?
规定:要注意算法的效率
分析:
乍一想有点乱。先找几个数计算一下:
1
[1], 3, 4
1, [3], 4, 7, 10
1, 3, [4], 7, 9, 10, 13
其中这个9提醒我们,虽然单纯的2x+1或3x+1一定是递增的,但是前一个数的3x+1有可能大于后一个数的2x+1。因此,当要在序列u中取“下一个数”计算它的2x+1和3x+1时,如何选取?
笨办法是用一个列表保存序列u,每计算出一个新的2x+1和3x+1时,都遍历一遍当前的列表,然后找到适当的位置插入。这显然不符合本题对于效率的要求。
换一个角度思考:如果我们不是用一个列表,而是用两个列表表示序列u呢?这两个列表分别保存2x+1和3x+1的值。由于它们一定是递增的,新元素只要直接append在队尾即可。而“选取下一个数”的动作,相当于从两个列表的队首依次挑出较小的那一个。这道题目进一步变形为:两个已经各自按从小到大顺序排列的列表,如何合并为一个从小到大排序的列表?
实现要点:
1. 高效的队列:
用deque。这篇文章比较了deque, queue, 和list的性能。
2. 两个已经各自按从小到大顺序排列的列表,如何合并为一个从小到大排序的列表?
取两个队首的最小值,并pop该最小值元素。下一次循环仍然取两个队首的最小值。
代码参考:
from collections import deque def dbl_linear(n): h = 1; cnt = 0; q2, q3 = deque([]), deque([]) while True: if (cnt >= n): return h q2.append(2 * h + 1) q3.append(3 * h + 1) h = min(q2[0], q3[0]) if h == q2[0]: h = q2.popleft() if h == q3[0]: h = q3.popleft() cnt += 1
posted on 2017-05-30 16:16 jennyz_2017 阅读(231) 评论(0) 编辑 收藏 举报