【发布时间】:2017-04-10 15:58:28
【问题描述】:
我正在尝试在 python3 中实现这个问题。从 1 到 10,000 的整数流的答案应该是 1213,我没有得到。我怀疑我的堆实现存在问题,而不是 main() 函数中的实际解决方案。
问题陈述:这个问题的目标是实现“中值维护”算法。文本文件包含从 1 到 10000 的整数列表,未排序;您应该将其视为一串数字,一个接一个到达。设 xi 表示文件的第 i 个编号,第 k 个中值 mk 定义为数字 x1,…,xk 的中值。 (所以,如果 k 是奇数,那么 mk 是 x1,…,xk 中的第 ((k+1)/2) 个最小的数;如果 k 是偶数,那么 mk 是 x1 中的第 (k/2) 个最小的数, …,xk。)
求 10000 个中位数之和,以 10000 为模。
#A = [4, 1, 3, 2, 16, 9, 10, 14, 8 , 7]
max_heap, min_heap = [], []
M, max_size, min_size, data_count, heap = 0, 0, 0, 0, True #True: MAX, False: MIN
def main():
global M
data = list(map(int, open('Median.txt').read().splitlines()))
#data = [2, 1, 3, 4, 5, 6, 7, 8, 9, 10]
insert(min_heap, data[0], not heap)
M += data[0]
insert(max_heap, data[1], heap)
M += data[1]
del data[:2]
for x in data:
if x < max_heap[0]:
insert(max_heap, x, heap)
else:
insert(min_heap, x, not heap)
if abs(max_size - min_size) > 1:
if max_size > min_size:
y = extract(max_heap, heap)
insert(min_heap, y, not heap)
else:
y = extract(min_heap, not heap)
insert(max_heap, y, heap)
if (min_size + max_size)%2 == 0:
M += max_heap[0]
else:
if max_size > min_size:
M += max_heap[0]
else:
M += min_heap[0]
print(max_heap, min_heap)
print(len(max_heap), len(min_heap))
print(M%10000)
def parent(i):
return i//2
def left(i):
return 2*i
def right(i):
return (2*i) + 1
def heapify(A, i, heap):
l, r = left(i), right(i)
if heap:
largest = None
if l < max_size and A[l] > A[i]:
largest = l
else:
largest = i
if r < max_size and A[r] > A[largest]:
largest = r
if largest != i:
A[i], A[largest] = A[largest], A[i]
heapify(A, largest, heap)
else:
smallest = None
if l < min_size and A[l] < A[i]:
smallest = l
else:
smallest = i
if r < min_size and A[r] < A[smallest]:
smallest = r
if smallest != i:
A[i], A[smallest] = A[smallest], A[i]
heapify(A, smallest, heap)
def buildHeap(A, heap):
global max_size, min_size
if heap:
max_size = len(A)
else:
min_size = len(A)
for i in reversed(range(len(A)//2)):
heapify(A, i, heap)
def insert(A, key, heap):
global max_size, min_size
if heap:
if max_size == len(A):
A.append(key)
else:
A[max_size] = key
max_size += 1
insertUtils(A, parent(max_size), heap)
else:
if min_size == len(A):
A.append(key)
else:
A[min_size] = key
min_size += 1
insertUtils(A, parent(min_size), heap)
def insertUtils(A, i, heap):
heapify(A, i, heap)
if parent(i) != 0:
insertUtils(A, parent(i), heap)
heapify(A, parent(i), heap)
def extract(A, heap): #THE PROBLEM IS HERE I BELIEVE!
global max_size, min_size
if heap:
if max_size < 1:
raise Exception('Heap underflow!')
max = A[0]
A[0] = A[max_size - 1]
max_size -= 1
heapify(A, 0, heap)
return max
else:
if min_size < 1:
raise Exception('Heap underflow!')
min = A[0]
A[0] = A[min_size - 1]
min_size -= 1
heapify(A, 0, not heap)
return min
main()
'''
buildHeap(A, heap)
insert(A, 17, heap)
for i in range(11):
print(A)
print(extract(A, heap))
insert(A, 18, heap)
print(A)
print(extract(A, heap))
'''
我知道,我问了很多,这是一个很长的代码。但我真的很感激一些帮助!谢谢! :)
【问题讨论】:
-
你写了什么代码来测试这个?在我看来,维护一个列表,在每个数字之后对其进行排序,并提取第 k/2 或 k/2+1 个数字对我来说似乎很明显将是对小值的有效检查(在这种情况下,10000 是一个小值。
-
@AustinHastings 确实是,但使用堆会提供更好的性能。如果我们使用快速排序之类的方法,我们将获得 O(logn) 时间的堆和 O(nlogn) 时间的排序方法。计数排序可能为 O(n),但堆仍然更好。我的疑问在于我对堆的实现!至于测试,我确实用非常小的数字进行了测试,比如 10,它似乎在那里工作。但它不适用于 10000。:/ 测试代码都在那里,它被注释了!
-
如果您怀疑代码在
extract中,为什么不只拿您的那部分代码并测试它是否正常工作?如果测试失败,您可以用heapq.heapify替换您自己对heapify的定义,以查看是否修复了您的测试,依此类推。 ericlippert.com/2014/03/05/how-to-debug-small-programs 可能会有所帮助。 -
@PaulHankin 哇!为此非常感谢!实际上,我一直在努力提出正确的问题。我尝试过,但有时我的日程安排迫使我在这里在线转储代码以希望得到答案,这太耗时了。我会尝试自己调试它,并研究'heapq'!再次感谢!
标签: python algorithm data-structures heap