Here是问题所在。我的解决方案是:
import sys
LIST_ITEM = []
NUMBER_OF_TEST_CASES = int(raw_input())
def non_decreasing(my_list):
if len(my_list) < 2:
return my_list
my_list.sort()
return my_list
if __name__ == "__main__":
if NUMBER_OF_TEST_CASES >= 1000001 or NUMBER_OF_TEST_CASES <= 0:
sys.exit()
for val in range(1, NUMBER_OF_TEST_CASES+1):
x = int(raw_input())
if x >= 1000001 or x<0:
sys.exit()
else:
LIST_ITEM.append(x)
values = non_decreasing(LIST_ITEM)
for i in values:
print i
但它告诉我Time Limit Exceeded
。 Here is my solution link
答案 0 :(得分:3)
简单的答案就是简介!我使用:
生成数据import random
out = open('foobar.txt', 'w')
total = random.randint(100000, 1e6)
out.write('%s\n' % total)
for x in xrange(total):
out.write('%s\n' % random.randint(0, 1e6))
然后我使用命令time python -m cProfile -o foo.profile foo.py < foobar.txt > fooout.txt && gprof2dot -f pstats foo.profile | dot -Tpng -o foo_profile.png
进行测试。这会使用gprof2dot工具生成这个漂亮的图形,并报告运行所花费的时间(在我的系统上具有266k输入行的1.9秒)。 sort -n foobar.txt > foo_sorted.txt
是我的黄金标准,约为0.41秒。
因此,您可以看到44.81%的时间花在基本代码上,38.82%用于raw_input,14%用于排序。
接下来我们开始优化。
首先是将代码放入方法中。只需在所有代码周围添加def main()
,最后if __name__ == '__main__': main()
。对我来说,削减了运行时间约5%,减少到1.8秒,并将raw_input移动到我们负载的最高百分比。
让我们看看我们是否可以减少这种情况。也许用直接使用sys.stdin替换raw_input?我假设raw_input是为交互式使用而设计的,并且可能没有很好地描述,因为它(可能)并非用于大量使用。通过用诸如sys.stdin.readline()之类的东西替换raw_input,我们应该使用更有效的代码路径。对我而言,运行时间从1.8秒降至0.952秒。节省一半!这是现在的代码和配置文件输出。
import sys
def non_decreasing(my_list):
if len(my_list) < 2:
return my_list
my_list.sort()
return my_list
def main():
LIST_ITEM = []
NUMBER_OF_TEST_CASES = int(sys.stdin.readline().strip())
if NUMBER_OF_TEST_CASES >= 1000001 or NUMBER_OF_TEST_CASES <= 0:
sys.exit()
for x in sys.stdin:
x = int(x.strip())
if x >= 1000001 or x<0:
sys.exit()
else:
LIST_ITEM.append(x)
values = non_decreasing(LIST_ITEM)
for i in values:
print i
if __name__ == '__main__':
main()
所以这是一个好的开始。我们现在不到原始运行时的一半。让我们来看看现在的速度有多慢。 main函数,sort,strip()和append。也许我们可以优化主要的东西?好吧,我注意到我们正逐一打印出这些线条。我们可以用一个sys.stdout.write()来切换它,看看是否有帮助?我试过sys.stdout.writelines([str(x) for x in values])
它实际上看起来比较慢,所以我觉得打印效率很高。让我们坚持下去。
我们还能减少什么?也许if x >= 1000001 or x<0:
声明?这完全是必要的吗?看起来我们可以通过删除它来轻松删除几百分之一秒。
还有什么?也许整个non_decreasing事情是不必要的,我们可以只使用LIST_ITEM.sort()?我想你的检查和额外的函数调用实际上并没有加快速度。是的,加快了一点!
理想情况下,在这一点上我们会做一些事情,比如不从输入中删除换行符,排序为字符串然后将其写出来。不幸的是,这没有得到理想的排序:(所以让我们尝试一些替代方案
for x in sys.stdin: values.append(x[:-1])
x.rstrip()
x.rstrip('\n')
values = sys.stdin.split('\n')
values = sys.stdin.read().splitlines()
values = sys.stdin.readlines()
在我的测试中,#1上的变体是最快的并保持正确性,在〜.783s。这是我的最终代码:
import sys
def main():
NUMBER_OF_TEST_CASES = int(sys.stdin.readline().strip())
if NUMBER_OF_TEST_CASES >= 1000001 or NUMBER_OF_TEST_CASES <= 0:
sys.exit()
values = [int(x) for x in sys.stdin.readlines()]
values.sort()
for i in values:
print i
if __name__ == '__main__':
main()
最终的gprof2dot个人资料信息......
答案 1 :(得分:2)
不要排序!
只需创建一个长度为1e6的零数组(也许是numpy),每当遇到数字i时,通过列表设置读取[i] = 1,然后打印出所有非零条目。
我认为这有效:
import numpy as np
import sys
nn = 1000000
a = np.zeros(nn+1, dtype=np.int)
for l in sys.stdin:
a[np.int(l)]=1
for i in xrange(nn+1):
if a[i]: print i
我希望有办法加快i / o。
答案 2 :(得分:1)
由于输入数据值和大小限制为10 ^ 6,因此您可以简单地初始化10 ^ 6值的数组并跟踪出现的值。排序和重复检测“免费提供”。
此方法将具有初始成本(初始化阵列),但对于大输入尺寸则值得。
实施例: 导入数组 来自sys import stdin 来自itertools import repeat
low = 1000001
high = -1
data = array.array('i', repeat(-1, 1000000))
count = int(stdin.readline().strip())
while count:
v = int(stdin.readline().strip())
count -= 1
data[v] = v
low = min(v, low)
high = max(v, high)
for v in xrange(low, high+1):
if data[v] > 0:
print v
请注意,我使用了array
,因为预先知道了大小和类型,因此我们可以绕过使用list
带来的开销。
如果对内存使用有限制,可以使用位数组而不会减小data
的大小,但在设置和迭代值时会产生一些额外的开销(和复杂性)。