寻找最小的K个数 python实现

该博客介绍了如何使用Python实现寻找最小的K个数的算法。通过建立K个元素的最大堆并遍历剩余元素,与堆顶元素比较并更新,达到O(n*logk)的时间复杂度。此外,还提到了寻找第K大值的方法,借助快速排序能达到线性时间复杂度。文章引用了CSDN博主的文章作为参考来源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

寻找最小的k个数
题目描述:5.查找最小的k个元素
题目:输入n个整数,输出其中最小的k个。

例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。


思路来自结构之法http://blog.csdn.net/v_july_v/article/details/6370650


方法一:

建K个元素的最大堆,Xmax为堆顶元素,然后遍历余下的n-k个元素,如果大于Xmax,与其交换,更新堆。所以时间复杂度为O(n*logk)

#!/usr/bin/env python
# -*- coding: utf-8 -*
#查找最小的k个树

def heapAdjust(A, i, length):
	pa = i
	child = 2*i + 1
	tmp = A[i]
	while child < length:
		if child < length-1 and A[child] < A[child+1]:
			child += 1
		if A[pa] >= A[child]:
			break
		else:
			A[pa],A[child] = A[child],A[pa]
			pa = child
			child = 2*pa + 1


def findKmin(A, k, length):
	for i in range(k/2)[::-1]:
		heapAdjust(A, i, k)
	print 'The heap is :', A[:k]
	for i in xrange(k,length):
		if A[i] < A[0]:
			A[i],A[0] = A[0],A[i]
			heapAdjust(A, 0, k)
	print 'The result is :', A[:k]

if __name__ == '__main__':
	A = [6,3,7,2,9,1,4,5,11,10,8]
	lens = len(A)
	findKmin(A, 10, lens) 

方法二:

类似快速排序。如果主元随机选取或者五化中项的中项,时间复杂度可以达到O(n)。

下面的算法不是找最小的k个值,而是寻找第k大的值,找到了第k大的值,因为之前已经经过了快拍,所以找到最小的k个值也就不难了,时间复杂度可以达到线性的复杂度。详情请参考http://blog.csdn.net/v_july_v/article/details/6403777。

首先利用快速排序将数组A化分为A[0:m],A[m+1,length-1]

if par == k-1:
    return A[par]
elif k-1 < par:
    return findKth(s, 0, par-1, k)
else:
    return findKth(s, par+1, n, k)
完整代码如下:


#!/usr/bin/env python
# -*- coding: utf-8 -*
#利用q_select查找第k大的值
def partition(s, m, n):
	#s is a list
	key = s[n-1]
	l,r = m,n-2
	while True:
		while l <= n-2 and s[l] <= key:
			l += 1
		while r>= m and  s[r] > key:
			r -= 1
		if l < r:
			s[l],s[r] = s[r],s[l]
		else:
			break
	s[l],s[n-1] = s[n-1],s[l]
	return l

def medin3(s, m, n):
	md = m + (n-m)/2
	if s[m] > s[md]:
		s[m],s[md] = s[md],s[m]
	if s[m] > s[n]:
		s[m],s[n] = s[n],s[m]
	if s[md] > s[n]:
		s[md],s[n] = s[n],s[md]
	s[md],s[n-1] = s[n-1],s[md]
	return s[n-1]

def findKth(s, m, n, k):
	if k-1 > n or  k-1 < m:
		return False
	if m<=n:
		medin3(s, m, n)
		par = partition(s, m, n)
		if par == k-1:
			return A[par]
		elif k-1 < par:
			return findKth(s, 0, par-1, k)
		else:
			return findKth(s, par+1, n, k)
	


if __name__ == '__main__':
	A = [6,3,7,2,9,1,4,5,11,10,8]
	lens = len(A)
	print findKth(A, 0, lens-1, 6) 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值