选择问题——选出第K个最大的元素

最近在读《数据结构与算法分析(C语言描述)》,在优先队列(堆)一节中,作者总结了关于“选择问题——求第k个最大的元素”的几种思路,在此简单总结一下:

第一种

将这N个数读进一个数组中,再通过某种简单的算法,比如冒泡排序、选择排序等,以递减顺序将数组进行排序,然后返回位置k上的元素。假设使用最简单的排序算法,则运行时间为O(N2)

第二种

这是对第一种算法的简单优化。申请一个大小为k的数组,然后先把前k个元素读入数组并以递减顺序进行排序。接着,将剩下的元素再逐个读入。当新元素被读到时,如果它小于数组中的第k个元素则忽略,否则将其放到数组中正确的位置上(就是插入排序啊!),同时将数组中最后一个元素挤出数组。当算法终止时,位于第k个位置上的元素就是最终结果,即第k个最大的元素。

该算法的平均运行时间为O(N?k),但是最差时间为O(N2)

第三种

简单来说:建最大堆!

将N个元素读入数组,然后对该数组执行BuildHeap算法(就是将这N个元素进行建堆,当然也可以边读数边建堆),最后,执行k次DeleteMin操作(就是删除根结点,也就是删除当前堆中最大的那个数)。从该堆中最后提取的那个元素就是我们的答案。

时间复杂度分析:

  • 如果使用BuildHeap,构造堆的最坏情形用时是O(N),而每次DeleteMin用时O(logN)(要随时调整堆),由于有k次DeleteMin,因此总运行时间为O(N+klogN)。
  • 如果k=O(N/logN),那么运行时间取决于BuildHeap操作,即O(N)
  • 对于大的k的值,运行时间为O(klongN)

第四种

算是第二种和第三种思路的结合。

也就是用堆来实现大小为k的数组S,前k个元素通过调用一次BuildHeap,以总时间O(k)被置入堆中,处理其余每个元素的时间为O(1)(检测元素是否进入数组)再加上时间O(longk)(在必要时删除根结点并插入新元素)。因此总的时间为O(k+(N?k)longk)=O(Nlongk)。

时间: 2024-10-03 04:09:10

选择问题——选出第K个最大的元素的相关文章

排序 2:选择排序 - 不断选出剩余数组中最小的元素

选择排序过程:首先,选出数组中最小的元素,将它与数组中第一个元素交换,然后找出次小的元素,并将它与数组中第二个元素交换...直至整个数组排序完成.即通过不断选出剩余数组中最小的元素实现. 选择排序时间复杂度:O(N^2) 实现程序: void Selection_sort(Item a[], int l, int r) { for(int i = l; i < r; i++) //最后一个无需交换 { int min = i; for(int j = i + 1; j <= r; j++) {

优先队列的应用:求序列第 k 个最大的元素

优先队列[堆]的应用:     选择问题:输入时N 个元素以及一个整数k ,这N 个元素的集可以是全序的.该选择问题是要找出第 k 个最大的元素... 有多种解决方案: 1A算法:把这些元素读入数组,并对其进行排序,返回适当的元素.假设使用的是简单排序算法,时间复杂度是O(N^2). 1B算法:将k 个元素读入一个数组,并对其进行排序.这些元素的最小者在第k 个位置上,一个一个的处理其余的元素.当一个元素开始被处理时,它先与第k 个元素进行比较,如果该元素大,则将第k 个元素出去,该元素放在其余

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

在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 示例 2: 输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4 说明: 你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度.思路方法:这道题思路就挺简单的,考查的就是对排序算法的了解.就用排序算法把数组元素按照降序排列,最后返回排序好的数组中下标为k-1的元素即是答

Leetcode 215、数组中第k个最大的元素

题目链接:kth-largest-element-in-an-array 方法1: 使用快速排序. 1.对数组进行partition,从left到right随机选择一个主元pivot,将pivot与left的元素交换位置. 另索引 j 初始为left,扫描从left + 1到right的元素,若小于pivot,则将其与 ++j 处的元素交换. 这样当扫描结束,left的元素即主元pivot,从left + 1到 j 的元素都大于pivot,从 j + 1到right的元素都小于等于pivot.

使用队列求解杨辉三角的第K层的所有元素

Java代码   package queue; import java.util.concurrent.ConcurrentLinkedDeque; /** * Created by Lanxiaowei * Craated on 2016/12/12 9:03 * 求解杨辉三角的第K层的所有元素 * 使用队列求解 */ public class YHTriangleWithQueue { public static void main(String[] args) throws Interru

LeetCode OJ:Kth Smallest Element in a BST(二叉树中第k个最小的元素)

Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. Note: You may assume k is always valid, 1 ≤ k ≤ BST's total elements. 求二叉树中第k个最小的元素,中序遍历就可以了,具体代码和另一个Binary Tree Iterator差不多其实,这题由于把=写成了==调bug调了好久,细心细心啊啊

选择问题(选择数组中第K小的数)

由排序问题可以引申出选择问题,选择问题就是选择并返回数组中第k小的数,如果把数组全部排好序,在返回第k小的数,也能正确返回,但是这无疑做了很多无用功,由上篇博客中提到的快速排序,稍稍修改下就可以以较小的时间复杂度返回正确结果. 代码如下: #include<iostream> using namespace std; #define Cutoff 3 int A[13] = {81,94,11,96,12,35,17,95,28,58,41,75,15}; void Swap(int &

选择问题,自定义k=N/2为最大值!

方法: k之前的先排序,最大值给k. 之后的逐个比较,大于k直接覆盖,否则k不变. 代码:      package com.Edward.suanfa; import java.util.Random; class getmax{ int getmax_(int a[],int k){//数组a[],k为指定最大值 int max=a[0]; int temp; int len=a.length-1; for(int i=0;i<=k;i++){ if(max>a[i]){ temp=a[i

Openjudge-计算概论(A)-找和为K的两个元素

描述: 在一个长度为n(n < 1000)的整数序列中,判断是否存在某两个元素之和为k. 输入第一行输入序列的长度n和k,用空格分开.第二行输入序列中的n个整数,用空格分开.输出如果存在某两个元素的和为k,则输出yes,否则输出no. 样例输入 9 10 1 2 3 4 5 6 7 8 9 样例输出 yes思路:这题是用了递归,不用也可以,直接循环判断即可.代码如下: 1 #include<stdio.h> 2 int f() 3 { 4 int i,j,n,k; 5 int a[100