问题:

在未排序的数组中找到第 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个或者最小的前k个之类。

常规方法有以下几种:

1.排序:

O(n logn)。

2.堆(该方法尤其适用于海量数据,因为内存中只需要维护k大小的堆,其他方法需要把海量数据全部移到内存中进行操作):

O(n log k)

用一个大小为k的堆,如果是求第k大,那么我们使用最小堆(为什么是最小堆看不懂没关系,这就说)。比如一个数据集有n个元素,假设我们(神奇的提前知道了!)最大的几个元素依次是x1,x2,x3,且x1、x2、x3都分布在数据集的后半部(假设n很大),而且k为3,即我们想求的就是x3。

步骤:

我们定义一个长度3的容器heap,先放入前3个数据,建立最小堆。然后我们从第4个元素开始遍历,每次遍历到一个元素nums[i],如果nums[i]>heap.top(),那么我们就pop掉当前的堆顶,并放入nums[i],重新维护最小堆性质。遍历完毕之后,最小堆的堆顶就是我们要求的数。

解释:

重申一次,我们想找的TOP-K,在本问题中就是前3大的数字。由于最小堆的堆顶是整个堆里最小的数字,所以如果有其他数字比这个堆顶大,说明这个堆顶一定不在最终的前3大数字里,所以我们理所当然的用当前数字去替换当前堆顶。

由于我们已经知道了x1、x2、x3是最大的三个数,遍历到他们时一定都有x1/x2/x3大于当时各自的堆顶从而push进堆,并且不可能有第4个数字比他们三个大从而把他们三个踢出堆。故最终堆里的三个数字就是x1、x2、x3,而且堆顶是三个数中最小的那个(x3),也就是我们想要的第3大的数。

时间复杂度为n logk,遍历n个元素,每次调整堆需要logk时间,在k比n小的情况下,比第一种排序算法节省大量时间。

容易理解,如果求第k小,那么我们对应的使用最大堆,解法完全一样。

代码:

 class Solution {
public:
int findKthLargest(vector<int>& nums, int k)
{
priority_queue<int,vector<int>,greater<int> >min_heap;
for(int num:nums)
{
min_heap.push(num);
if(min_heap.size()>k)
{
min_heap.pop();
}
}
return min_heap.top();
}
};

3.划分(partition):

O(n),将数组划分为左右两部分,如果中枢轴右侧元素大于k个,那对右侧区间继续划分,否则对左侧区间进行划分。

和快排的区别在于,快排划分之后,分别对左右子区间递归划分,时间是n+2*n/2+4*n/4+...=O(n logn)

该算法只会对一侧子区间进行递归划分,时间为n+n/2+n/4+n/8+...=O(n)

注意在取基准数的时候一定要随机化处理,否则时间效率会大大增加!

 class Solution {
public:
int findKthLargest(vector<int>& nums, int k)
{
srand(time());
return partition(nums,,nums.size()-,k);
}
int partition(vector<int>& nums,int le,int ri,int k){
if(le>=ri){
return k==?nums[le]:-;
}
int random_pos=rand()%(ri-le);
swap(nums[le+random_pos],nums[ri]);//随机化基准数,基准数为nums[ri]
int i=le-,j=le,stable=nums[ri];
while(j<ri){
if(nums[j]<stable){
swap(nums[++i],nums[j]);
}
++j;
}
swap(nums[i+],nums[ri]);
//i+1为划分枢轴
if(ri-i==k){
return nums[i+];
}
else if(ri-i>k){
return partition(nums,i+,ri,k);
}
else{
return partition(nums,le,i,k-ri+i);
}
}
};

基准数不加随机化:

基准数加随机化:

215. 数组中的第K个最大元素(TOP-K问题)的更多相关文章

  1. [Swift]LeetCode347. 前K个高频元素 | Top K Frequent Elements

    Given a non-empty array of integers, return the k most frequent elements. Example 1: Input: nums = [ ...

  2. Java实现 LeetCode 215. 数组中的第K个最大元素

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

  3. 215. 数组中的第K个最大元素 + 快速排序 + 大根堆

    215. 数组中的第K个最大元素 LeetCode-215 另一道类似的第k大元素问题:https://www.cnblogs.com/GarrettWale/p/14386862.html 题目详情 ...

  4. LeetCode 215——数组中的第 K 个最大元素

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

  5. 《剑指offer》第五十三题(数组中数值和下标相等的元素)

    // 面试题53(三):数组中数值和下标相等的元素 // 题目:假设一个单调递增的数组里的每个元素都是整数并且是唯一的.请编程实 // 现一个函数找出数组中任意一个数值等于其下标的元素.例如,在数组{ ...

  6. LeetCode 80 Remove Duplicates from Sorted Array II(移除数组中出现两次以上的元素)

    题目链接:https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/#/description 给定一个已经排好序的数组 ...

  7. javascript 数组中出现的次数最多的元素

    javascript 数组中出现的次数最多的元素 var arr = [1,-1,2,4,5,5,6,7,5,8,6]; var maxVal = arr[0]; // 数组中的最大值 var min ...

  8. 算法练习之合并两个有序链表, 删除排序数组中的重复项,移除元素,实现strStr(),搜索插入位置,无重复字符的最长子串

    最近在学习java,但是对于数据操作那部分还是不熟悉 因此决定找几个简单的算法写,用php和java分别实现 1.合并两个有序链表 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两 ...

  9. 剑指offer——58数组中数值和下标相等的元素

    题目三: 数组中数值和下标相等的元素. 假设一个单调递增的数组里的每个元素都是整数并且是唯一的.请编程实现一个函数,找出数组中任意一个数值等于其下标的元素.例如,在数组{-3,-1,1,3,5}中,数 ...

  10. LeetCode题解 | 215. 数组中的第K个最大元素

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

随机推荐

  1. adworld easy_RSA | RSA算法

    题目描述: 解答出来了上一个题目的你现在可是春风得意,你们走向了下一个题目所处的地方 你一看这个题目傻眼了,这明明是一个数学题啊!!!可是你的数学并不好.扭头看向小鱼,小鱼哈哈一笑 ,让你在学校里面不 ...

  2. 框架里增加.env文件的作用

    在实际开发中我们常常遇到这样的问题,就是开发地点不固定,这就造成了我们需要频繁的更改数据库配置,给开发工作造成了麻烦,.env环境文件的出现解决了这个麻烦,我们只需要在不同的工作地点配置好.env文件 ...

  3. Nginx出现403 forbidden

    我装在linux上的nginx版本是1.16 当我在nginx/conf/nginx.conf文件里配置完代理 location /ds { root /home/nginx; index index ...

  4. Dalsa 8K彩色相机Camera link C#采图

    一个采图工具,所以界面做的很简单. private SapAcquisition m_Acquisition; private SapBuffer m_Buffers; private SapAcqT ...

  5. Java实现的上传并压缩图片功能【可等比例压缩或原尺寸压缩】

    本文实例讲述了Java实现的上传并压缩图片功能.分享给大家供大家参考,具体如下: 先看效果: 原图:1.33M 处理后:27.4kb 关键代码: package codeGenerate.util; ...

  6. 2019-08-22 纪中NOIP模拟A&B组

    T1 [JZOJ3229] 回文子序列 题目描述 回文序列是指左右对称的序列.我们会给定一个N×M的矩阵,你需要从这个矩阵中找出一个P×P的子矩阵,使得这个子矩阵的每一列和每一行都是回文序列. 数据范 ...

  7. 从0开始学算法--排序(1.12c++利用标准库排序)

    1,简单数组按升序排序 sort(a,a+n); #include <algorithm> #include <iostream> #include <cstring&g ...

  8. Progressbar 实例

    Progressbar 实例原创侠之大者为国为民 最后发布于2015-10-28 15:22:34 阅读数 5394 收藏展开Progressbar - orient 配置进度条的方向:"h ...

  9. 解决DFS Locations从Eclipse的Navigator中消失的问题

    尝试了这篇博客https://blog.csdn.net/qq_40120951/article/details/85028976所说的解决办法,但对我没用. 最后是重新打开Map/Reduce解决的 ...

  10. [CF1034B] Longest Palindrome - 贪心

    如果自己是回文串可以做中心 如果一个串和另一个串的转置相等则可以凑一对 优先配对 #include <bits/stdc++.h> using namespace std; int n,m ...