高效的队列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

 

转载于:https://www.cnblogs.com/netoops/p/6919172.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值