当前位置: 首页 > news >正文

LeetCode 算法:数组中的第K个最大元素 c++

原题链接🔗:数组中的第K个最大元素
难度:中等⭐️⭐️

题目

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:
输入: [3,2,1,5,6,4], k = 2
输出: 5

示例 2:
输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4

提示:

1 <= k <= nums.length <= 105
-104 <= nums[i] <= 104

  • 堆(Heap)是一种特殊的树状数据结构,它满足两个主要特性:

    1. 结构性:堆通常是一棵完全二叉树,这意味着除了最后一层外,其他每一层都被完全填满,并且最后一层的节点尽可能地集中在左侧。

    2. 堆属性:堆中的每一个节点都必须满足特定的顺序要求,这个要求可以是最大堆属性或最小堆属性。

      • 最大堆:任何一个父节点的值都大于或等于它的子节点的值。这意味着堆的根节点是所有节点中的最大值。
      • 最小堆:任何一个父节点的值都小于或等于它的子节点的值。这意味着堆的根节点是所有节点中的最小值。
  • 堆在计算机科学中广泛应用于各种算法和数据结构,特别是在需要快速访问最大元素或最小元素的场景中。例如,堆排序算法、优先队列的实现等。

  • 在编程语言中,堆通常通过优先队列(Priority Queue)这种抽象数据类型来实现。优先队列允许快速地插入新元素和删除(或检索)最大(或最小)元素。

  • 堆的常见操作包括:

    • 插入(Push):向堆中添加一个新元素。
    • 删除最大/最小元素(Pop):移除并返回堆中的最大(或最小)元素。
    • 查找最大/最小元素(Peek/Top):返回堆中的最大(或最小)元素,但不从堆中移除它。
  • 堆的实现可以通过数组来完成,其中每个元素的索引和其父节点或子节点的索引之间有一定的数学关系。例如,在数组表示的堆中,一个元素的父节点可以通过(i-1)/2计算得到,其中i是该元素的索引;其子节点可以通过2*i + 1(左子节点)和2*i + 2(右子节点)计算得到。

题解

  1. 解题思路:

在LeetCode上解决“数组中的第K个最大元素”问题,通常有几种不同的方法。这里我会介绍两种常见的解题思路:

  • 方法一:排序

    1. 排序:首先,对数组进行排序。
    2. 选择:然后,从排序后的数组中选择第K个元素。

    这种方法简单直观,但时间复杂度较高,尤其是在数组很大的情况下。排序通常需要O(n log n)的时间,其中n是数组的长度。

  • 方法二:使用堆(优先队列)

    1. 构建最小堆:使用一个容量为K的最小堆来存储数组中的前K个最大元素。
    2. 遍历数组:遍历数组中的每个元素。
      • 如果当前元素大于堆顶元素,并且堆还没有满(堆的大小小于K),则将堆顶元素移除,并将当前元素加入堆中。
      • 如果当前元素大于堆顶元素,并且堆已经满了,那么只需要将堆顶元素移除,并将当前元素加入堆中,这样堆始终保持大小为K。
    3. 堆顶元素:遍历结束后,堆顶元素就是第K个最大元素。

    这种方法的时间复杂度是O(n log K),因为每个元素最多被比较和交换K次。当K远小于n时,这种方法比排序更高效。

  • 方法三:快速选择算法(Quick Select)

    1. 选择主元:类似于快速排序,选择一个主元,将数组分为两部分,一部分包含所有比主元大的元素,另一部分包含所有比主元小的元素。
    2. 定位主元:根据主元的位置,确定第K个最大元素是在左侧还是在右侧。
    3. 递归:根据K的位置,递归地在左侧或右侧执行快速选择。

    快速选择算法的平均时间复杂度是O(n),但最坏情况下会退化到O(n^2)。

  1. c++ demo:
#include <iostream>
#include <vector>
#include <queue>
#include <functional>using namespace std;// 使用最大堆来找到第K个最大的元素
int findKthLargest(vector<int>& nums, int k) {priority_queue<int, vector<int>, greater<int>> maxHeap;for (int num : nums) {if (maxHeap.size() < k) {maxHeap.push(num);}else if (num > maxHeap.top()) {maxHeap.pop();maxHeap.push(num);}}return maxHeap.top();
}int main() {// 测试用例vector<int> nums = { 3,2,1,5,6,4 };int k = 2;// 调用函数并输出结果int result = findKthLargest(nums, k);cout << "The " << k << "th largest element is " << result << endl;return 0;
}
  • 输出结果:

The 2th largest element is 5

  1. 代码仓库地址:findKthLargest

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 网络安全入门教程(非常详细)从零基础入门到精通_网路安全 教程
  • 数智化底座:企业迈向智能未来的关键
  • VMware vSphere Replication 虚拟机备份及迁移实践
  • 美国一男子伪造死亡逃避抚养义务,获刑六年
  • 网站怎么做敏感词过滤,敏感词过滤的思路和实践
  • C++排序
  • 探索802.1X:构筑安全网络的认证之盾
  • 嵌入式学习day17(数据结构)
  • 【C++】深度解析:用 C++ 模拟实现 priority_queue类,探索其底层实现细节(仿函数、容器适配器)
  • WARNING XXX is not overriding the create method in batch
  • IDEA XML文件去掉黄色和绿色底色
  • Qt第十六章 多媒体Multimedia
  • fscan下载和使用
  • 预训练语言模型PLM(课程笔记)
  • 数据结构:栈、队列详解篇
  • #Java异常处理
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • 【刷算法】求1+2+3+...+n
  • 10个确保微服务与容器安全的最佳实践
  • FineReport中如何实现自动滚屏效果
  • GitUp, 你不可错过的秀外慧中的git工具
  • Git初体验
  • Linux各目录及每个目录的详细介绍
  • SpringBoot 实战 (三) | 配置文件详解
  • Terraform入门 - 3. 变更基础设施
  • 安卓应用性能调试和优化经验分享
  • 回流、重绘及其优化
  • 基于webpack 的 vue 多页架构
  • 跨域
  • 聊聊flink的BlobWriter
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 使用putty远程连接linux
  • 数据结构java版之冒泡排序及优化
  • 智能合约Solidity教程-事件和日志(一)
  • Android开发者必备:推荐一款助力开发的开源APP
  • FaaS 的简单实践
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #14vue3生成表单并跳转到外部地址的方式
  • #define、const、typedef的差别
  • #include<初见C语言之指针(5)>
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (003)SlickEdit Unity的补全
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (LeetCode C++)盛最多水的容器
  • (web自动化测试+python)1
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (九)c52学习之旅-定时器
  • (十)T检验-第一部分
  • (新)网络工程师考点串讲与真题详解
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)VirtualBox安装增强功能
  • (一)基于IDEA的JAVA基础1
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转载)OpenStack Hacker养成指南