首页 > 其他分享 >数组中的第K个最大元素

数组中的第K个最大元素

时间:2024-05-28 15:25:51浏览次数:9  
标签:场景 最大 复杂度 元素 数组 minHeap 小根堆 log

主管问到这个问题(数组中的第K个最大元素)。
我首先答了partition算法时间复杂度O(n)空间复杂度O(1)。主管说不行,要用堆。然后(我回答)用建大根堆,取前k,时间复杂度O(n+klogn)初始化O(n),pop出k个O(klogn),空间复杂度O(k)(使用原数组建堆,pop出k个)。主管说都不行,然后(主管)给了个小根堆的算法,逐个把数插入堆中。维持小根堆大小为k,如果超出就出堆。这样的话,相当于把n-k个小的pop出去了剩下的小根堆就存了k个最大的。时间复杂度O(nlogk)空间复杂度O(k)
主管预设了场景了,说是数据规模很大,但是只要前几个,也就是说n很大k很小。所以说nlogk是不可能比得过n+klogn的。哪一个都没我的算法好啊。无语。

主管给出的要求通常是希望看到你对算法和数据结构的全面理解以及实际场景中的应用。针对你提到的查找前 k 大元素的问题,主管希望你使用小根堆,这是因为它在处理某些特定场景(如数据规模非常大但只需前几大元素)时具有显著优势。以下是对这几种方法的详细分析,以及为什么在这种场景下使用小根堆是一个更优的选择。

常见解法及其时间和空间复杂度

1. Partition Algorithm(基于快速选择的算法)

  • 时间复杂度: 平均 O(n),最坏 O(n^2)
  • 空间复杂度: O(1)

这种方法在实际应用中可能会遇到最坏情况(例如,选择的基准总是最大或最小元素),导致性能不稳定。

2. 大根堆(Max-Heap)

  • 构建堆的时间复杂度: O(n)
  • 取前 k 大元素的时间复杂度: O(k log n)
  • 总体时间复杂度: O(n + k log n)
  • 空间复杂度: O(1)(使用原数组)

这种方法在数据量很大时,构建堆的时间复杂度是 O(n),而取前 k 大元素的时间复杂度是 O(k log n)。虽然总体时间复杂度比较好,但对数据量极大而 k 很小时,仍然可能不够高效。

3. 小根堆(Min-Heap)

  • 时间复杂度: O(n log k)
  • 空间复杂度: O(k)

这种方法的思路是维持一个大小为 k 的小根堆,当堆的大小超过 k 时,将堆顶元素(最小的元素)移除。这样,最终堆中保存的就是前 k 大的元素。

为什么小根堆在这种场景下更优?

在这种场景下,n 很大而 k 很小,使用小根堆的时间复杂度是 O(n log k),这比大根堆的 O(n + k log n) 更有优势。具体来说:

  • 插入操作: 每次插入一个元素到堆中,操作时间是 O(log k),而总共需要插入 n 次,总时间是 O(n log k)。
  • 堆的大小: 由于堆的大小始终维持在 k,因此空间复杂度是 O(k)。

小根堆实现代码示例

import java.util.PriorityQueue;

class Solution {
    public int findKthLargest(int[] nums, int k) {
        // 创建一个小根堆
        PriorityQueue<Integer> minHeap = new PriorityQueue<>(k);
        
        // 遍历数组,将元素插入堆中
        for (int num : nums) {
            if (minHeap.size() < k) {
                // 如果堆的大小小于 k,直接插入
                minHeap.offer(num);
            } else if (num > minHeap.peek()) {
                // 如果堆的大小已经达到 k,并且当前元素大于堆顶元素
                // 先移除堆顶元素,再插入当前元素
                minHeap.poll();
                minHeap.offer(num);
            }
        }
        
        // 堆顶元素就是第 k 大的元素
        return minHeap.peek();
    }
}

总结

  • Partition Algorithm 适用于一般场景,但在极端情况下性能不稳定。
  • 大根堆 在需要多次取最大值时非常有效,但在处理极大数据集而只需少量最大值时,时间复杂度不如小根堆。
  • 小根堆n 很大而 k 很小的情况下,具有更优的时间复杂度 O(n log k) 和适度的空间复杂度 O(k),因此在这种特定场景下是最优选择。

主管希望看到你能够根据具体的场景和需求选择最合适的算法。理解并灵活运用不同的数据结构和算法,是展示你能力的关键。

标签:场景,最大,复杂度,元素,数组,minHeap,小根堆,log
From: https://www.cnblogs.com/echo1937/p/18218086

相关文章

  • 学习JavaScrip 中常见的6种数组方法
    学习JavaScrip中常见的6种数组方法1.find()方法2.forEach()方法3.join()方法4.map()方法5.reduce()方法6.filter()方法1.find()方法find()方法取得数组中第一个满足回调函数中指定条件的元素。如果没有元素满足条件,这个方法返回undefined。下面的例子能够帮助你......
  • 有序数组的平方
    文章目录有序数组的平方解题思路有序数组的平方给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。示例1:输入:nums=[-4,-1,0,3,10]输出:[0,1,9,16,100]解释:平方后,数组变为[16,1,0,9,100]排序后,数组变为......
  • leedcode【349】. 两个数组的交集——Java解法
    Problem: 349.两个数组的交集题目思路解题方法复杂度Code效果题目给定两个数组nums1和nums2,返回它们的交集。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序。示例1:输入:nums1=[1,2,2,1],nums2=[2,2]输出:[2]示例2:输入:nums1=[......
  • 数组
    数组1.数组概述数组是相同类型数据的有序集合数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成;其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标访问它们2.数组声明创建首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法......
  • Day 6| 242.有效的字母异位词 、349. 两个数组的交集 、 202. 快乐数 、 1. 两数之和
    242.有效的字母异位词建议:这道题目,大家可以感受到数组用来做哈希表给我们带来的遍历之处。题目链接/文章讲解/视频讲解:https://programmercarl.com/0242.有效的字母异位词.html思考很简单的一道题,需要记住python获取ascii值的函数时ord()classSolution:defisAnag......
  • 代码随想录算法训练营第第20天 | 654.最大二叉树 、617.合并二叉树 、700.二叉搜索
    654.最大二叉树又是构造二叉树,昨天大家刚刚做完中序后序确定二叉树,今天做这个应该会容易一些,先看视频,好好体会一下为什么构造二叉树都是前序遍历题目链接/文章讲解:https://programmercarl.com/0654.最大二叉树.html视频讲解:https://www.bilibili.com/video/BV1MG411G7ox......
  • 代码随想录算法训练营第五天|242(有效的字母异位词),349(两个数组的交集),202(快乐数)
    哈希C#常用的数据结构:[]Array,ArrayList数组和动态数组List集合HashSet哈希集合(无重复值)HashTable哈希表(obj,obj的键值对)Dictionary<T,T>泛型的哈希表什么时候考虑Hash数据结构?需要高效的判断一个值是否存在在一个容器中时。容器不允许重复值(HashSet或哈希表的......
  • char数组初始化
    原文:https://www.cnblogs.com/cfans1993/p/6404034.html初始化的三种情况:charstr[10]="Hello";charstr[10]={'H','e','l','l','o','\0'};charstr[10]={'H'};charstr[10]={0};charstr......
  • P1734 最大约数和
    变形01背包#include<bits/stdc++.h>usingnamespacestd;constintN=1010;ints;intn,m;intv[N],w[N],f[N];intaccum(intp){//预先处理约数之和 intans=0; for(inti=1;i<=p-1;i++){//因为不包括它本身因此p-1;if(p%i==0)ans+=i; ......
  • Java数组
    1、数组概述数组是相同类型数据的有序集合。数组描述的是相容类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。数组下标是从0开始的。2、数组声明创建首先必须声明数组变量,才能在程序中使用......