问题:

在n个数中找出最大的k个数。

多次求min()或求max()

最简单的方法是对大小为k的数组进行n次求min计算(或者对大小为n的数组进行k次求max计算)最后能够找出最大k个数。复杂度是O(nk)。

代码:

def topK_mink(num_list,k):
topK=num_list[:k]
for i in range(k,len(num_list)):
topK_min=min(topK)
if num_list[i]>topK_min:
topK[topK.index(topK_min)]=num_list[i]
return topK

使用小根堆

维护一个大小为k的小根堆,从头到尾扫描n个数,如果当前数比堆顶大,替换堆顶,这样扫描到最后堆中保存的是最大的k个数。复杂度是O(nlogk)

代码:

import heapq
def topK_heapq(num_list,k):
array = []
for i in range(len(num_list)):
if len(array) < k:
heapq.heappush(array, num_list[i])
else:
array_min = array[0]
if num_list[i] > array_min:
heapq.heapreplace(array, num_list[i])
topK=array
return topK

使用大根堆

维护一个大小为n的大根堆,每次弹出堆顶元素,共弹出k次。复杂度O(klogn)

代码:略

快速选择BFPRT

借用快速排序中思想,在快排中每次用一个轴将数组划分为左右两部分,轴左边的数都小于轴,轴右边的数都大于轴,轴所在的位置和排好序后的位置相同。这里只要找到第k大的数作为轴进行划分,那么就找到了最大的k个数。期望复杂度是:O(n)

代码:

def topK_partition(arr,k):

    def partition(num_list,left,right,k):
flag=num_list[left]
i=left
j=right
while i<j:
#print(flag,i,j,num_list)
if num_list[i]>flag:
i+=1
elif num_list[j]<flag:
j-=1
else:
if num_list[i]==num_list[j]:
j-=1
num_list[i],num_list[j]=num_list[j],num_list[i]
#print(flag,num_list)
if i<k:
return partition(num_list,i+1,right,k)
if i>k:
return partition(num_list,left,i-1,k)
return num_list[:k] return partition(arr[:],0,len(random_list)-1,k)

测试代码:

import numpy as np
import time
def judge(ans,k1):
for i in ans:
if i-k1<0:
return False
return True
k=1000
n=25000
random_list=[np.random.randint(n*0.5) for i in range(n)]
real_ans=sorted(random_list,reverse=True)[:k+1]
k1=real_ans[-1] t1=time.time()
ans=topK_heapq(random_list,k)
t2=time.time()
print(judge(ans,k1),t2-t1) t1=time.time()
ans=topK_partition(random_list,k)
t2=time.time()
print(judge(ans,k1),t2-t1) t1=time.time()
ans=topK_mink(random_list,k)
t2=time.time()
print(judge(ans,k1),t2-t1)

结果:

topK_mink()没有任何优势

topK_partition()的运行时间不稳定

topK_heapq()运行时间稳定

虽然期望复杂度topK_partition()优于topK_heapq(),但是topK_partition()计算开销比topK_heapq()多。

当n小时,用topK_heapq()比topK_partition()好

当n大,k小时,topK_heapq()用时也较短。

当n大,k大时(n>10,000,000),用topK_partition()。

从数组中找到topK的元素(序号)的更多相关文章

  1. 在未排序的数组中找到第 k 个最大的元素

    在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 ...

  2. PHP从数组中找到指定元素的位置

    群里有人问,有个数组五个元素 分为1到5  现在要求 循环找出3元素的索引,怎么做性能才是最高. 我不知道哪个性能最高,但是我想提出可以用多种方式进行查找,然后进行比较选择. 我想,最简单最基础的 应 ...

  3. 【一起刷LeetCode】在未排序的数组中找到第 k 个最大的元素

    题目描述 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 ...

  4. 《程序员代码面试指南》第八章 数组和矩阵问题 在数组中找到出现次数大于N/K 的数

    题目 在数组中找到出现次数大于N/K 的数 java代码 package com.lizhouwei.chapter8; import java.util.ArrayList; import java ...

  5. python经典面试算法题4.1:如何找出数组中唯一的重复元素

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. [百度面试题] 难度系数:⭐⭐⭐ 考察频率:⭐⭐⭐⭐ 题目描述 ...

  6. 【Matlab开发】matlab删除数组中符合条件的元素与散点图绘制

    [Matlab开发]matlab删除数组中符合条件的元素与散点图绘制 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ matlab删除数组中符合条件的元素 如 ...

  7. Js判断数组中是否存在某个元素

    Js判断数组中是否存在某个元素 方法一:indexOf(item,start); Item:要查找的值:start:可选的整数参数,缺省则从起始位子开始查找. indexOf();返回元素在数组中的位 ...

  8. JavaScript从数组中删除指定值元素的方法

    本文实例讲述了JavaScript从数组中删除指定值元素的方法.分享给大家供大家参考.具体分析如下: 下面的代码使用了两种方式删除数组的元素,第一种定义一个单独的函数,第二种为Array对象定义了一个 ...

  9. [java]删除数组中的某一个元素

    package org.company.project.test; import java.util.Arrays; import java.util.Scanner; public class Ar ...

随机推荐

  1. java基础之----分布式事务tcc

    最近研究了一下分布式事务框架,ttc,总体感觉还可以,当然前提条件下是你要会使用这个框架.下面分层次讲,尽量让想学习的同学读了这篇文章能加以操作运用.我不想废话,直接上干货. 一.什么是tcc?干什么 ...

  2. 基于Arduino的红外遥控

    1.红外接收头介绍  一.什么是红外接收头?  红外遥控器发出的信号是一连串的二进制脉冲码.为了使其在无线传输过程中免受其他红外信号的干扰,通常都是先将其调制在特定的载波频率上,然后再经红外发射二极管 ...

  3. Go语言教程之结构体

    Hello,大家好,我是小栈君,最近因为工作的事情延误了一点分享的进度,但是我会尽量抽时间分享关于IT干货知识,还希望大家能够持续关注"IT干货栈"哦. 闲话不多说,今天给大家继续 ...

  4. Keystone V3 API Examples

    There are few things more useful than a set of examples when starting to work with a new API. Here a ...

  5. 为BlueLake主题增加自定义icon图标

    一.前言 hexo 的 Bluelake 主题是我一直在用的,简单大方,很喜欢.但最近有了添加自定义 icon 图标的需求,比如,添加 "地址"."扫一扫".& ...

  6. selenium之窗口滚动

    在这里和大家分享一下,selenium里面常用于处理窗口滚动的方法. location_once_scrolled_into_view 一般用于定位窗口底部元素.将窗口拉到最底部. window.sc ...

  7. CTF-Keylead(ASIS CTF 2015)

    将keylead下载到本地用7-ZIP打开,发现主要文件 keylead~ 在ubuntu里跑起来,发现是个游戏,按回车后要摇出3,1,3,3,7就能获得flag. 拖进IDA 直接开启远程调试,跑起 ...

  8. 【原创】CentOS8双网卡绑定

    1. NAT网络配置(所有服务器): # yum install bash-completion # cd /etc/sysconfig/network-scripts/ bond0配置: # vim ...

  9. NOI2.5 8465:马走日

    描述 马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. 输入 第一行为整数T ...

  10. Android的学习之路一

    在Android的道路上越走越远==,本着一颗童心去学习,没想到最后会成为自己的职业.看到过知乎上写的,并不是兴趣使比尔盖茨以及乔布斯他们成就斐然,而是他们真正的牛逼使得即使买大饼也能成为世界首富.然 ...