所谓“第(前)k大数问题”指的是在长度为n(n>=k)的乱序数组中S找出从大到小顺序的第(前)k个数的问题。
采用元素下沉法,维护一个k大小的最小堆,对于数组中的每一个元素判断与堆顶的大小,若堆顶较大,则不管,否则,弹出堆顶,将当前值插入到堆中,继续调整最小堆。时间复杂度O(n * logk)
注意:heap和array的关系;Find_heap_kth函数里面range的索引范围;
def heap_build(parent,heap):
child = 2*parent+1
while child len(array):
return None
heap = array[:k]
for i in range(k,-1,-1):
heap_build(i,heap)
for j in range(k,len(array)):
if array[j]>heap[0]:
heap[0] = array[j]
heap_build(0,heap)
return heap[0]
print(Find_heap_kth([2,1,4,3,5,9,8,0,1,3,2,5],6))
由于是要找 k 个最大的数,所以没有必要对所有数进行完整的排序。每次只保留 k 个当前最大的数就可以,然后每次对新来的元素跟当前 k 个树中最小的数比较,新元素大的话则插入到数组中,否则跳过。循环结束后数组中最小的数即是我们要找到第 k 大的数。 时间复杂度 (n-k)logk
注意:嵌套for循环里面,比较的对象;以及range的范围
def Find_Kth_max(array,k):
for i in range(1,k):
for j in range(i,0,-1):
if array[j] > array[j-1]:
array[j],array[j-1] = array[j-1],array[j]
else:
pass
for i in range(k,len(array)):
if array[i] > array[k-1]:
array[k-1] = array[i]
for j in range(k-1,0,-1):
if array[j] > array[j-1]:
array[j],array[j-1] = array[j-1],array[j]
else:
pass
return array[k-1]
print(Find_Kth_max([2,1,4,3,5,9,8,0,1,3,2,5],3))
从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。时间复杂度近似为O(n)
def partition(num, low, high):
pivot = num[low]
while (low < high):
while (low < high and num[high] > pivot):
high -= 1
while (low < high and num[low] < pivot):
low += 1
num[low],num[high] = num[high],num[low]
num[high] = pivot
return high,num
def findkth(num,low,high,k): #找到数组里第k个数
index=(partition(num,low,high))[0]
print((partition(num,low,high))[1])
if index==k:return num[index]
if index
总觉得这个快排实现的有点问题。。
附加
1 求中位数实际上是第k大数的特例。
2 如果需要找出N个数中最大的K个不同的浮点数呢?比如,含有10个浮点数的数组(1.5,1.5,2.5,3.5,3.5,5,0,- 1.5,3.5)中最大的3个不同的浮点数是(5,3.5,2.5)。解答:上面的解法均适用
3 如果是找第k到第m(0