在下面的任务中重新安排问题,在Python 2.7中发布问题和我的代码。我的具体问题,
while counter < f
的循环) ,我想知道我应该做的是(1)将剩余的未安排的任务/频率放回堆中,以及(2)找到要处理的下一个高频任务?对于公告第2点,我测试了我的代码是否正常(ok表示我的代码返回最少的执行时间加上等待时间),但如果有任何错误,我应该做(1)和(2)除了我当前的实现,请随时指出。
问题
给定一组任务,如[A,A,B]和int k,这是两个相同任务之间的等待时间。如果允许重新排列任务,请计算最小总执行时间。假设每个单独任务的执行是1。
在上面的例子中 A A B,k = 1,没有重新排列,执行时间为4:
A wait A B
1 1 1 1
重新排列,执行时间为3:
A B A
1 1 1
源代码,
from collections import defaultdict
import heapq
def rearrange_tasks(tasks):
freq = defaultdict(int)
for t in tasks:
freq[t] += 1
h = []
heapq.heapify(h)
result = [0] * len(tasks)
for t,f in freq.items():
heapq.heappush(h, (-f, t))
while len(h) > 0:
f, t = heapq.heappop(h)
f = -f
write_index = 0
while write_index < len(result) and result[write_index] != 0:
write_index += 1
counter = 0
while write_index < len(result) and counter < f:
result[write_index] = t
write_index += 2
counter += 1
# write tasks which have to be consecutive
write_index = 0
while counter < f:
if result[write_index] != 0:
write_index += 1
else:
result[write_index] = t
write_index += 1
counter += 1
return result
def calculate_execution_time(tasks, k):
exec_time = 0
for i, t in enumerate(tasks):
if i == 0:
exec_time += 1
continue
if t == tasks[i-1]:
exec_time += k
exec_time += 1
else:
exec_time += 1
return exec_time
if __name__ == "__main__":
tasks = ['A', 'A', 'B']
result = rearrange_tasks(tasks)
print result
print calculate_execution_time(result, 1)
tasks = ['A', 'A', 'A', 'A', 'C', 'D', 'E', 'E', 'B', 'B', 'B']
result = rearrange_tasks(tasks)
print result
print calculate_execution_time(result, 1)
修改1 :
使用条件while write_index < len(result) and counter < f:
(条件counter < f:
答案 0 :(得分:1)
看起来您的代码会在某些输入上引发错误。例如,我试过这个:
['A', 'A', 'B', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C']
...
File "orig.py", line 22, in rearrange_tasks
result[write_index] = t
IndexError: list assignment index out of range
以下是一些建议的更改。他们更少关注优化速度,更多关注算法清晰度。我有点怀疑你应该过多担心速度 - 你的输入有多大以及有多少不同的任务值?该算法似乎主要是线性的,特别是如果不同任务值的数量很小。
from collections import Counter
from heapq import heapify, heappop, heappush
def rearrange_tasks(tasks):
# Make a heap of (-FREQ, TASK) tuples.
freq = Counter(tasks)
h = [(-f, t) for t, f in freq.items()]
heapify(h)
result = []
prev = None
while h:
# Get the most frequent item.
f, t = heappop(h)
# If it is a repeat and if there are other items,
# put it back and grab 2nd most frequent item instead.
if t == prev and h:
item = (f, t)
f, t = heappop(h)
heappush(h, item)
# Put selected item back on heap, after adjusting frequency.
if f < -1:
heappush(h, ((f + 1), t))
# Add task to the result.
result.append(t)
prev = t
return result
def calculate_execution_time(tasks, k):
n = 0
prev = None
for t in tasks:
n += 1 + int(t == prev) * k
prev = t
return n
def run(tasks):
result = rearrange_tasks(tasks)
assert Counter(tasks) == Counter(result)
print
print 'len =', len(tasks)
print 'time =', calculate_execution_time(result, 1)
print 'result =', ''.join(result)
if __name__ == "__main__":
run('AAB')
run('AABCCCCCCCC')
run('AAAACDEEBBB')
run('AAAACDEEBBBBBBBBBBBB')