我是Python的新手,我目前正致力于解决问题,以提高我的编码技能。目前,我正处理一个问题,我必须stable sort
输入并输出反向稳定的排序值。我已经对它进行了编程并在网站的在线评判中执行了代码,并且对于一个测试用例(不知道测试用例),我得到Memory Limit Exceeded
错误。因此,经过一些研究,我了解到代码中发生了memory leak
,代码并不完全有效。所以我已经安装了python' memory_profiler
来监控进程的内存消耗以及对代码内存消耗的逐行分析。
请在下面找到从memory_profiler
获取的输入详细信息,代码,输出和内存分析分析。
输入:
8
1 2
16 3
11 2
20 3
3 5
26 4
7 1
22 4
代码:
from collections import OrderedDict
@profile
def test_1():
print "Enter the number: "
n = raw_input()
k = []
v = []
print "Enter ID and M: "
for i in range(0,int(n)):
a, b = raw_input().split(' ')
k.append(a)
v.append(b)
d = OrderedDict(zip(k,v))
sorted_items = sorted(d.items(), key=lambda (k,v):int(v), reverse=True)
for i, j in sorted_items:
print i, j
if __name__ == '__main__':
test_1()
输出:
Line # Mem usage Increment Line Contents
================================================
2 10.520 MiB 0.000 MiB @profile
3 def test_1():
4 10.531 MiB 0.012 MiB print "Enter the number: "
5 10.551 MiB 0.020 MiB n = raw_input()
6 10.551 MiB 0.000 MiB k = []
7 10.551 MiB 0.000 MiB v = []
8 10.551 MiB 0.000 MiB print "Enter ID and M: "
9 10.551 MiB 0.000 MiB for i in range(0,int(n)):
10 10.551 MiB 0.000 MiB a, b = raw_input().split(' ')
11 10.551 MiB 0.000 MiB k.append(a)
12 10.551 MiB 0.000 MiB v.append(b)
13
14 10.551 MiB 0.000 MiB d = OrderedDict(zip(k,v))
15 10.555 MiB 0.004 MiB sorted_items = sorted(d.items(), key=lambda (k,v):int(v), reverse=True)
16 10.555 MiB 0.000 MiB for i, j in sorted_items:
17 10.555 MiB 0.000 MiB print i, j
预期输出(我能够获得所需的输出):
3 5
26 4
22 4
16 3
20 3
1 2
11 2
7 1
此代码对于更高输入或更高数字是否效率不高?从分析中我可以看到只有较少的内存利用,但对于那个特定的测试用例,我可以看到内存利用率超过16MB。 有人能告诉我我在哪里做错了。我的方法是错误的还是流程错了?你能否告诉我为什么我无法按预期获得输出。提前致谢。任何帮助将不胜感激。
答案 0 :(得分:1)
我正在撰写评论但是时间太长了,所以我想我不妨将其升级为答案。
首先,profile
装饰器仅使用相当多的内存。如你所见:
from memory_profiler import profile
@profile
def foo():
pass
我得到了
Line # Mem usage Increment Line Contents
================================================
2 28.5 MiB 0.0 MiB @profile
3 def foo():
4 28.5 MiB 0.0 MiB pass
你的号码可能会有所不同(我正在运行Python 3,在IDE中也不少),但它与你的功能基本相同。几乎所有的内存使用都来自@profile
行(10.520 MiB),你的函数添加的内容(参见增量列)很简单(0.36 MiB)。
结果是你看起来不应该有任何问题(如果你发布的内容已经是你的整个代码了,我想它就是这样)。我不知道哪个测试用例可能会给你Memory Limit Exceeded
。我们真的需要知道测试用例是什么来调查问题。
尽管如此,一项改进可以使您的代码更有效,特别是对于大量输入。您无需在代码中构建中间列表(k
和v
)。直接写到字典:
d = OrderedDict()
for i in range(int(n)): # Note you don't need range(0, x); just range(x)
a, b = raw_input().split() # No need for an argument to split, either
d[a] = b
更好的是,您可以避免for
循环并使用更高效的生成器表达式:
d = OrderedDict(raw_input().split() for _ in range(int(n)))
生成器表达式是(foo something_like_a_for_loop)
形式的表达式(形式描述here);如果它是函数的唯一参数,则可以省略周围的括号。它就像一个列表在很多方面:你可以使用for
进行迭代,你可以使用list
从中获取一个列表,只要有一个迭代器就可以使用它。但是当列表很长时,它比等效列表占用的空间要少得多。 (但也存在差异:gen expr可以在上迭代,无法编入索引,也没有len
等等。您可以阅读更多相关信息{{ 3}}。)
您可以进行其他一些小改进。全部纳入下面的重写
def test_1():
n = int(raw_input('Enter the number: '))
d = OrderedDict(raw_input().split() for _ in range(n))
sorted_items = sorted(d.items(), key=lambda k_v: int(k_v[1]), reverse=True)
for i, j in sorted_items:
print i, j