我是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。谁能告诉我我哪里做错了。是我的方法错了还是心流错了?你能告诉我为什么我无法按预期获得输出吗?提前谢谢。任何帮助将不胜感激。
我正在写评论,但它太长了,所以我想我不妨将其升级为答案。
首先,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
你的数字可能会有所不同(我在IDE中运行Python 3),但你的函数基本上是一样的。几乎所有内存使用量都来自@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)
的表达式(此处为正式描述);如果它是函数的唯一参数,则可以省略周围的括号。它在很多方面都像一个列表:你可以使用for
迭代它,你可以使用list
从中获取一个列表,你可以在需要迭代器时使用它。但是,当列表很长时,它比等效列表占用的空间要少得多。(但也存在差异:一个 gen expr 只能迭代一次,不能被索引并且没有len
,等等。您可以在此处阅读有关它的更多信息。
您还可以进行其他小改进。全部纳入下面的重写中
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