【发布时间】:2018-01-05 10:08:15
【问题描述】:
我正在编写一个程序,它获取农民挤奶的开始和结束时间列表,并确定 >=1 头奶牛挤奶的最长时间和没有奶牛挤奶的最长时间。
在其中,我尝试过使用此功能。这是一个完整搜索的练习,但是当有很多数据时这还不够快(我认为是因为有 n^2 次迭代)。
timesIS 只是一个按开始顺序递增的时间列表,timesDE 是一个按结束顺序递减的相同时间列表。 timeIndex 是开始的位置。对于最长的挤奶间隔,我的程序稍后会为每个索引执行此操作并返回最长的间隔。
在保持完整搜索的同时,我怎样才能提高效率(也许切换到更接近 n 次的搜索)?
def nextCease(TimesIS, timesDE, timeIndex):
latestTime = TimesIS[timeIndex][1]
for j in range (0, len(timesDE)):
for i in range (0, len(timesDE)):
if timesDE[i][0]<=latestTime and timesDE[i][1]>=latestTime:
latestTime = timesDE[i][1]
if latestTime == timesDE[0][1]:
return latestTime
break
return latestTime
这是一小段数据输入(第一行是农民的数量):
6
100 200
200 400
400 800
800 1600
50 100
1700 3200
我认为这是一个最小、完整且可验证的示例:
from operator import itemgetter
times = [[100,200], [200,400], [400,800], [800,1600], [50,100], [1700,3200]
def nextCease(TimesIS, timesDE, timeIndex):
latestTime = TimesIS[timeIndex][1]
for j in range (0, len(timesDE)):
for i in range (0, len(timesDE)):
if timesDE[i][0]<=latestTime and timesDE[i][1]>=latestTime:
latestTime = timesDE[i][1]
if latestTime == timesDE[0][1]:
return latestTime
break
return latestTime
timesIS = sorted(times[:], key=itemgetter(0)) #increasing starttimes
timesDE = sorted(times[:], key=itemgetter(1), reverse=True) #decreasing endtimes
longestIntervalMilk = 0
for i in range (0, len(times)):
interval = nextCease(timesIS, timesDE, i) - timesIS[i][0]
if interval > longestIntervalMilk:
longestIntervalMilk = interval
longestIntervalNoMilk = 0
latestFinish = 0
for i in range (0, len(times)):
latestFinish = nextCease(timesIS, timesDE, i)
timesIS2 = timesIS[:]
while(timesIS2[0][0] < latestFinish):
nextStartExists = True
del timesIS2[0]
if timesIS2 == []:
nextStartExists = False
break
if nextStartExists == True:
nextStart = timesIS2[0][0]
longestIntervalNoMilk = nextStart - latestFinish
print(str(longestIntervalMilk) + " " + str(longestIntervalNoMilk) + "\n"))
编辑:与此同时,我写了这个。它为一个很长的列表提供了错误的输出(它是 1001 行,所以我不会在这里重新打印它,但你可以在 http://train.usaco.org/usacodatashow?a=iA4oZAAX7KZ 找到它)我很困惑为什么:
times = sorted(times[:], key=itemgetter(0))
def longestMilkInterval(times):
earliestTime = times[0]
latestTime = times[0][1]
interval = 0
for i in range (1, len(times)):
if times[i][1] > latestTime and times[i][0] <= latestTime:
if times[i][1] - earliestTime[0] > interval:
interval = times[i][1] - earliestTime[0]
latestTime = times[i][1]
else:
earliestTime = times[i]
latestTime = times[i][1]
print(earliestTime)
return interval
def longestNoMilkInterval(times):
earliestTime = times[0][1]
interval = 0
for i in range (0, len(times)):
if times[i][0] >= earliestTime:
if times[i][0] - earliestTime > interval:
interval = times[i][0] - earliestTime
break
else:
earliestTime = times[i][1]
return interval
输出应该是912 184(>=1 头奶牛,0 头奶牛)。
【问题讨论】:
-
是的,使用
bisect在排序的值列表中进行搜索。但我们可以通过minimal reproducible example 提供帮助。没有数据,就无法优化您的代码。 -
谢谢!我已经发布了更多内容,现在我正在阅读这篇文章,并且会尽力而为。
-
@Jean-FrançoisFabre 我忘了给你加标签,抱歉。
-
直接回答时不需要。所以我已经读过了。
-
嗯,我明白了。