解法 1
将数组直接排序然后截取后半段的数据。
nums = [1,2,3,4,5,6,7,8,9,10]
k = 4
nums.sort()
print(nums[-k:])
解法 2
使用快速排序的方法,将数据分为两组,其中一组数据的任意一个数都比另一个数中的任意一个数大。假设N个数储存在数组S中,我们从数组S中随机找出一个元素X,把数组分为两部分S(a)和S(b)。S(a)中的元素大于等于X,S(b)中的元素小于X。这个时候存在两种情况:
1、S(a)中元素的个数小于K,S(a)中所有数和S(b)中最大的K-|S(a)|个元素就是数组S中最大的K个数。
2、S(a)中元素大于或等于K,则返回S(a)中的最大的K个数。
这里直接采用递归的方法进行求解比较简单。
import random
def kbig(S, K):
if K <= 0:
return []
if len(S) <= K:
return S
[Sa, Sb] = Partiton(S)
return kbig(Sa,K)+kbig(Sb,K-len(Sa))
def Partiton(S):
Sa, Sb = [], []
i = random.randint(0,len(S)-1)
S[0], S[i] = S[i], S[0]
P = S[0]
for i in range(1,len(S)):
Sa.append(S[i]) if S[i] > P else Sb.append(S[i])
Sa.append(P) if len(Sa) < len(Sb) else Sb.append(P)
return [Sa,Sb]
S = [10,2,3,4,5,6,7,8,9,10]
K = 4
res = kbig(S, K)
print(res)
解法 3
寻找N个数的最大的K个数,本质上就是寻找最大的K个数中的最小数。可以使用二分查找的策略。
def LookforNum(nums,data): #寻找nums中大于等于data的个数
n = len(nums)
iCount = 0
for i in range(n):
if nums[i] >= data:
iCount += 1
return iCount
nums = [11,2,3,4,5,6,7,8,9,10] #这里假设都是整数
k = 4
vmax , vmin = max(nums), min(nums)
vmid = 0
while vmax - vmin > 0.5:
vmid = vmin + (vmax - vmin) * 0.5
if LookforNum(nums,vmid)>=k:
vmin = vmid
else:
vmax = vmid
res = []
for i in range(len(nums)):
if nums[i] >= vmid:
res.append(nums[i])
print(res)
解法 4
使用小根堆来存放数据。先是预存k个元素进入小根堆,然后不断更新堆中的元素。
# 创建小根堆
def CreateHeap(arr):
for i in range(len(arr)):
CurIndex = i
FatherIndex = (CurIndex-1)//2
while arr[CurIndex] < arr[FatherIndex]:
arr[CurIndex], arr[FatherIndex] = arr[FatherIndex], arr[CurIndex]
return arr
nums = [11,2,3,4,5,6,7,8,9,10]
k = 4
arr = nums[0:k]
arr = CreateHeap(arr)
for i in range(k,len(nums)):
if nums[i] > arr[0]:
arr[0] = nums[i]
CurIndex = 0
# arr[i]的孩子节点为arr[2*i+1]和arr[2*i+2]
# 这里更新小根堆
while CurIndex < k:
ChildIndex = 2*CurIndex+1 # 寻找孩子节点
if ChildIndex>=k:
break
if ChildIndex < k-1 and arr[ChildIndex+1] < arr[ChildIndex]: # 寻找孩子节点较小的一个值
ChildIndex = ChildIndex+1
if arr[ChildIndex] < arr[CurIndex]: # 如果父节点大于较小子节点
# 交换两个节点
arr[ChildIndex], arr[CurIndex] = arr[CurIndex], arr[ChildIndex]
CurIndex = ChildIndex
else:# 如果父节点小于等于较小子节点
break
print(arr)
也可使用python中heapq堆库。
解法 5
使用count数组来记录每个整数出现的个数,从后往前遍历来获取结果。
nums = [11,2,3,4,5,11,7,10,10,10]
k = 4
MAXN = max(nums)
count = [0]*(MAXN+1)
for i in range(len(nums)):
count[nums[i]] += 1
sumCount, res = 0, []
for i in range(MAXN, -1, -1):
sumCount += count[i]
if count[i]:
while count[i]:
res.append(i)
count[i] -= 1
if sumCount >= k:
break
print(res[:k])