算法:高效的队列deque

一、题目:

有一个序列u,满足:

1. 第一个元素是1

2. 此后任意一个元素x,2x+1和3x+1也必定在u中

现给定整数n,求序列u中的第n个元素是什么?并输出该序列

规定:要注意算法的效率

二、分析

先找几个数计算一下:

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该最小值元素。下一次循环仍然取两个队首的最小值。

四、过程分析

五、实现代码

 1 #-*- coding:utf-8 -*-
 2 __author__ = 'Administrator'
 3 
 4 from collections import deque
 5 
 6 #返回列表中第n+1个元素
 7 def deq_linear(Len):
 8     count_n=1;h=1;d1=deque([]);d2=deque([])
 9     d_total=deque([1])
10     while True:
11         if count_n>=Len:
12             return h,d_total
13         d1.append(2*h+1)
14         d2.append(3*h+1)
15         Min=min(d1[0],d2[0])
16         if d1[0]==Min:
17             h=d1.popleft()
18             d_total.append(h)
19         else:
20             h=d2.popleft()
21             d_total.append(h)
22         count_n=count_n+1
23 
24 if __name__=="__main__":
25     Len=10
26     h,li=deq_linear(Len)
27     print("长度为 %d 的序列:%s" %(Len,list(li)))
28     print("该序列第 %d 个元素为:%d" %(Len,h))
29     #输出:
30     #长度为 10 的序列:[1, 3, 4, 7, 9, 10, 13, 15, 19, 21]
31     #该序列第 10 个元素为:21
View Code
原文地址:https://www.cnblogs.com/yizhenfeng168/p/6926524.html