【OJ - 堆】找数组中的第K个最大元素(C++ STL - priority_queue)

news/2024/5/20 7:02:52 标签: c++, 算法, , leetcode, 后端

文章目录

      • OJ - 找数组中的第K个最大元素
        • 解题思路
        • 思路1:暴力求解,排序
        • 思路2:建大
        • 思路3:建小,最优解

OJ - 找数组中的第K个最大元素

题目难度:中等

LeetCode链接:215. 数组中的第K个最大元素

题目描述

image-20211126134101521

解题思路

思路1:暴力求解,排序

使用头文件 <algorithm> 中的 sort 函数模板,直接排序,找到第k个最大的元素

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        // 对数组nums排序
        // 类模板参数默认是less,升序排序 <
        // 这里传类模板参数greater,降序排序 >
        sort(nums.begin(), nums.end(), greater<int>());
		// 返回第k个最大的元素
        return nums[k - 1];
    }
};
  • 时间复杂度:因为 sort 底层是快速排序,所以时间复杂度为 O ( N ∗ l o g N ) O(N*logN) O(NlogN)
  • 空间复杂度: O ( 1 ) O(1) O(1)

思路2:建大

使用排序,建立 n 个元素的大,做 k - 1 次删除操作后,此时顶元素就是第k个最大的元素

因为 C++ 的优先级队列 priority_queue 本质就是,所以这道题我没有自己建

【n 个元素的,插入和删除元素的时间复杂度都为 O(logN)】

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        // 建立 n 个元素的大,用迭代器区间[first,last)初始化
        priority_queue<int> maxHeap(nums.begin(), nums.end());
        
        /* 上述入操作也可以这样写:
        // 将数组nums中的元素依次放入优先级队列中
        priority_queue<int> maxHeap;  // priority_queue默认是大
        for(size_t i = 0; i < nums.size(); i++) {
            maxHeap.push(nums[i]);
        }
        */

        // popd顶元素k-1次后,此时的顶元素就是第k个最大的元素
        while(--k) {
            maxHeap.pop();
        }
        
        return maxHeap.top();
    }
};
  • 时间复杂度:向下调整建立 n 个数的大时间代价为 O(N);删除顶元素 k - 1 次(交换后删除,并向下调整)的时间代价为 O(klogN);相加为 O ( N + k l o g N ) O(N + klogN) O(N+klogN)
  • 空间复杂度:建立n个数的大,需要开空间存这n个数,所以为 O ( N ) O(N) O(N)

思路3:建小,最优解

思考:如果数组 nums 中的元素个数 n 特别大,前两种方法的弊端就出来了,那么如果做到时间和空间复杂度更优呢?

因为我们要找的是第 k 个最大的元素:

  • 建立 k 个元素的小,数组 nums 前 k 个元素依次放入小,此时的顶元素是中最小的元素,也是里面第 k 个最小的元素,

  • 然后把数组 nums 剩下的元素与顶比较,若大于顶则去掉顶,再将其插入,

  • 这样一来,里面存放的就是数组 nums 中的前 k 个最大元素,

  • 此时小顶元素也就是中的第 k 个最大的元素

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
		// 建立 k 个元素的小,传类模板参数 greater,将 priority_queue 定义成小
        priority_queue<int, vector<int>, greater<int>> minHeap;
        
        // 将数组 nums 前 k 个元素依次放入优先级队列中
        for(size_t i = 0; i < k; i++)
        {
            minHeap.push(nums[i]);
        }

        // 遍历nums剩下的元素,与顶比较,若大于顶则去掉顶,再将其插入
        for(size_t i = k; i < nums.size(); i++)
        {
            if(nums[i] > minHeap.top())
            {
                minHeap.pop();          // pop掉当前顶元素
                minHeap.push(nums[i]);  // 入数组元素
            }
        }
        
        // 结束后小顶元素就是第k个最大的元素
        return minHeap.top();
    }
};
  • 时间复杂度:建立 k 个数的小时间代价为 O(k);剩余 n - k 个数与顶元素比较一下,pop一下,push一下,时间代价为 O((N-k)*logk);相加为 O ( k + ( N − k ) l o g k ) O(k + (N-k)logk) O(k+(Nk)logk)

    当 n 远大于 k 时,这种方法更优,尤其是 n 大到内存中存不下。

  • 空间复杂度:建立 k 个数的大,需要开空间存这 k 个数,所以为 O ( k ) O(k) O(k)



http://www.niftyadmin.cn/n/1579649.html

相关文章

运维安全:远离故障的十大原则

2019独角兽企业重金招聘Python工程师标准>>> 故障是运维人员永远的痛。相信每一个运维人员的KPI中都有一项&#xff1a;可用性。可用性高就是不出故障&#xff0c;各个公司对可用性和故障评级的标准都不相同&#xff0c;但是避免故障的方法却是殊途同归。我们怎么避…

【C++】模板(template)进阶

文章目录一、非类型模板参数二、模板特化2.1 概念2.2 函数模板特化2.3 类模板特化① 全特化② 偏特化三、模板分离编译3.1 概念3.2 模板的分离编译① 程序编译&#xff08;⭐重要&#xff09;② 问题分析③ 解决方法四、总结一、非类型模板参数 模板参数分为「类型形参」与「非…

开源 免费 java CMS - FreeCMS-栏目页静态化参数 .

下载地址&#xff1a;http://code.google.com/p/freecms/ 栏目页静态化参数 在栏目页静态化时,系统会使用此栏目指定的模板文件(如未指定&#xff0c;默认为站点所选模板中的“栏目页面.html”文件)生成栏目页并传递以下参数。 参数 说明 contextPath 系统根路径 site 当前…

开源 免费 java CMS - FreeCMS-首页静态化参数 .

下载地址&#xff1a;http://code.google.com/p/freecms/ 首页静态化 在首页静态化时,系统会使用站点所选模板中的“首页.html”文件生成站点首页并传递以下参数。 参数 说明 contextPath 系统根路径 site 当前站点对象&#xff0c;类型为数据对象site contextPath 系统根…

构造函数的执行顺序

构造函数的执行顺序 一、C#中构造函数有几种。 1.静态构造函数 2.默认构造函数 3.带参数的构造函数 二、顺序如何执行呢&#xff1f; 先看代码&#xff1a; class MyClass{static MyClass(){Console.WriteLine("静态构造函数被调用。");}private static Component st…

FullCalendar 官方文档翻译3

1.与google日历连接&#xff0c;别忘记加入<script typetext/javascript srcjs/gcal.js/> events: $.fullCalendar.gcalFeed ("http://www.google.com/calendar/feeds/xuqi86gmail.com/private-660ae86cc26345cff3430480e8eea4bb/basic", { className:gca…

【二叉树进阶】二叉搜索树的结构、实现及应用

文章目录前言一、二叉搜索树的概念二、二叉搜索树的实现2.1 节点 & 树的整体结构2.2 默认成员函数的实现2.2.1 构造函数2.2.2 拷贝构造函数&#xff08;要弄懂&#xff09;2.2.3 赋值运算符重载&#xff08;要弄懂&#xff09;2.2.4 析构函数三、二叉搜索树的相关接口实现3…

【C++ - STL】set、map、multiset、multimap 容器(介绍、使用、应用场景)

文章目录前言一、set&#xff08;集合&#xff09;1.1 set容器介绍1.2 set的使用① set的常用接口② 使用举例排序去重1.3 总结二、multiset三、map&#xff08;映射&#xff09;3.1 map容器介绍3.2 键值对 - pair&#xff08;⭐核心 - 非常重要&#xff09;3.3 map的使用① ma…