L = [('key1', 14), ('key2', 20), ('key3', 13), ('key4', 10), ('key5', 11)]
假设我得到了如上所述的list
。每个元组的第二个元素在概念上表示块存储器的大小。这些块存储器是相邻的和顺序的。他们的关系可以表示为:
0 ____ 14 ____ 14 + 20 14 ____ + 20 + 13 14 ____ + 20 + 13 + 10 14 ____ + 20 + 13 + 10 + 11
现在用户会给我'绝对地址',我应该给他一个密钥来解密整个内存块。例如,如果他想访问地址'10',那么我应该为他返回key1。如果他想访问'15',那么我应该返回key2。
我的实施现在每次都要从头开始搜索。实际上,有许多内存块,用户希望一直访问。表现不好。
L = [('key1', 14), ('key2', 20), ('key3', 13), ('key4', 10), ('key5', 11)]
def get_key(address):
c = 0
offset = 0
for i in L:
if address < i[1] + offset:
break
c += 1
offset += i[1]
return c
print(get_key(15))
我如何改善表现?
数据结构没有 成为
list
(L)。但已知的事情应该是(1)块大小, (2)密钥,(3)用户将访问“绝对地址”。
根据Burhan Khalid的指示,最终代码如下(另见How to find the cumulative sum of numbers in a list?):
from bisect import bisect
from itertools import accumulate
L = [('key1', 14), ('key2', 20), ('key3', 13), ('key4', 10), ('key5', 11)]
markers = [i[0] for i in L]
boundaries = list(accumulate([i[1] for i in L]))
##offsets = []
##offsets.append(boundaries[0])
##for offset in boundaries[1:]:
## offsets.append(sum(offsets)+offset)
def buckets(value, boundaries, markers):
i = bisect(boundaries, value)
return markers[i]
print(buckets(67, boundaries, markers))
答案 0 :(得分:5)
L2 = [('key1', 14), ('key2', 34), ('key3', 47), ('key4', 57), ('key5', 68)]
总时间复杂度应为O(n)
,空间复杂度为O(n)
,每个查询的时间为O(logn)
。
答案 1 :(得分:4)
您可以使用数组对分算法将请求的数量放入正确的偏移量。
documentation for the bisect
module提供了以下示例,可以为此轻松修改:
>>> def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
i = bisect(breakpoints, score)
return grades[i]
>>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
['F', 'A', 'C', 'C', 'B', 'A', 'A']
以下是您将如何使用它(未经测试):
markers = [i[0] for i in initial_list_of_tuples]
boundaries = [i[1] for i in initial_list_of_tuples]
offsets = []
offsets.append(boundaries[0])
for offset in boundaries[1:]:
offsets.append(sum(offsets)+offset)
def buckets(value, boundaries, markers):
i = bisect(boundaries, value)
return markers[i]