寻找最大的K个数 (python)

解法 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])

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值