LeetCode HOT100系列题解之数组中的第K个最大元素(7/100)

news/2024/9/17 21:47:00/ 标签: leetcode

目录

题目:第K个最大元素. - 力扣(LeetCode)

题解

方法一 快速排序

方法二 桶排序

思考:各个排序的思路,以及时间复杂度是多少?

1. 冒泡排序(Bubble Sort)

2. 选择排序(Selection Sort)

3. 插入排序(Insertion Sort)

4. 快速排序(Quick Sort)

5. 归并排序(Merge Sort)

6. 堆排序(Heap Sort)


题目:第K个最大元素. - 力扣(LeetCode)

题解

方法一 快速排序

第K大数本身,这是一个经典的快速排序问题,以此做一个快速排序的复习。

需要注意的是,这个题严格规定时间为O(N),快排则是期望为线性O(N)的。

快速排序的思路:

选取一个基准(pivot),通过一趟排序将数据分成两部分:左边的都小于等于基准,右边的都大于基准。然后递归地对左右两部分进行快速排序。

举例(如果有错,理解就可以):

6 5 3 4 2 1

l = 0,  r = 5

i = -1, j = 6

x = q[0] = 6

while循环结束

i = 0 j = 5

swap(q[0], q[5])

k=4<=5,继续,递归走if

1 5 3 4 2

l = 0, r = 5

i = - 1,j = 6

x = q[0] = 1

while(i < j)

while(q [ ++ i ] < 1) 不存在 i = 0

while(q [ - - j ] > 1) j = 0

k = 4 >= 0

走else l = j + 1 = 1, r = 5

1 5 3 4 2 6

l = 1, r = 5

x = q[1] = 5

i = 0, j = 6

while(i < j)

while(q [ ++ i ] < 5) 不存在 i = 1

while(q [ - - j ] > 1) j = 4

swap(q[1], q[4])

1 2 3 4 5 6

l = 1, r = 4

i = 0, j = 5

x = q[1] = 2

i = j = 1

l = 2 ,r = 4

···

l = 4, r = 4 return q[4]

代码: 

class Solution {
public:int quick_select(vector<int>& q, int l, int r, int k) {if (l == r) return q[l];  // 只有一个元素时直接返回int i = l - 1, j = r + 1;int x = q[l];  // 选择第一个元素作为基准while (i < j) {while (q[++i] < x);  // 向右找第一个不小于 x 的元素while (q[--j] > x);  // 向左找第一个不大于 x 的元素if (i < j) swap(q[i], q[j]);  // 交换}// 判断 k 在左半部分还是右半部分if (k <= j) return quick_select(q, l, j, k);  // 在左半部分查找else return quick_select(q, j + 1, r, k);  // 在右半部分查找}int findKthLargest(vector<int>& nums, int k) {int n = nums.size();return quick_select(nums, 0, n - 1, n - k);  // 查找第 n-k 个最小的元素}
};

方法二 桶排序

该题给出的数据范围以及时间限制,实际上桶排序更符合要求。

代码:  

class Solution {
public:int findKthLargest(vector<int>& nums, int k) {vector<int> s(20010, 0);  // 初始化计数数组,大小为20010,用于存储[-10000, 10000]范围内的数字频率// 统计每个元素出现的次数for (int num : nums) {s[num + 10000]++;  // 将原数组元素映射到[0, 20010)的范围}// 从大到小遍历查找第k大元素for (int i = 20009; i >= 0; i--) {  // 从最大值开始遍历k -= s[i];if (k <= 0) {return i - 10000;  // 将索引还原为原数组的数值}}return -1;  // 如果没有找到(理论上不应到达这里)}
};

思考:各个排序的思路,以及时间复杂度是多少?

1. 冒泡排序(Bubble Sort)

  • 思路:重复地遍历要排序的列表,每次比较相邻的两个元素,如果它们的顺序错误就交换它们。每一轮遍历后,最大的元素都会“冒泡”到未排序部分的最后。
  • 时间复杂度:最坏情况下是 O(n^2)。
  • 稳定性:稳定(相同元素的相对位置不会改变)。
  • 特点:实现简单,但效率较低,适合小规模数据或教学用途。

2. 选择排序(Selection Sort)

  • 思路:每次从未排序部分选出最小(或最大)的元素,放到已排序部分的末尾。通过遍历找到最小值或最大值的位置,然后交换到正确的位置。
  • 时间复杂度:最坏情况下是 O(n^2)。
  • 稳定性:不稳定(相同元素的相对位置可能改变)。
  • 特点:比较次数固定为 n(n−1)/2,交换次数较少。

3. 插入排序(Insertion Sort)

  • 思路:将元素逐一插入到已排序部分的合适位置。初始时只有一个元素是已排序的,然后依次将未排序元素插入到前面已排序的部分。
  • 时间复杂度:最坏情况下是O(n^2),最优情况下是 O(n)(当输入已经有序)。
  • 稳定性:稳定。
  • 特点:适合小规模或基本有序的数据。

4. 快速排序(Quick Sort)

  • 思路:选取一个基准(pivot),通过一趟排序将数据分成两部分:左边的都小于等于基准,右边的都大于基准。然后递归地对左右两部分进行快速排序。
  • 时间复杂度:平均是 O(nlog⁡n),最坏情况下是 O(n^2)(当每次选的基准都是最大或最小值)。
  • 稳定性:不稳定。
  • 特点:在大多数情况下是最快的基于比较的排序算法,广泛使用。

5. 归并排序(Merge Sort)

  • 思路:将待排序数组分成两部分,递归地对两部分进行归并排序,然后将两部分合并成一个有序数组。
  • 时间复杂度:始终是O(nlogn)。
  • 稳定性:稳定。
  • 特点:适合大规模数据排序,特别是外部排序(如磁盘数据),但需要额外的空间来存储临时数据。

6. 堆排序(Heap Sort)

  • 思路:利用堆这种数据结构(通常是大顶堆或小顶堆)来排序。首先构造一个大顶堆(或小顶堆),然后反复将堆顶元素取出并重新调整堆,直到所有元素有序。
  • 时间复杂度:最坏情况下是 O(nlog⁡n)。
  • 稳定性:不稳定。
  • 特点:不需要额外的空间,适合大数据的内存排序。

http://www.ppmy.cn/news/1524661.html

相关文章

【Go - 拼接字符串】

在 Go 中&#xff0c;可以使用多种方式拼接字符串。以下是一些常见的方法&#xff1a; 使用 操作符 这是最简单的方式&#xff0c;适用于少量字符串的拼接。 str : "Hello, " "world!"使用 fmt.Sprintf 适用于需要格式化字符串的场景。 str : fmt.S…

维护左右边第一个小的值(滑动窗口)

前言&#xff1a;这个题目和我之前写的一个题目差不多&#xff0c;我们可以维护左右边第一个小的&#xff0c;然后我们就可以快速枚举 题目地址 #include <bits/stdc.h> using namespace std; #define ll long longconst int N (int)1e6 10; int a[N], h[N]; int qia…

SSM框架整合实战

本笔记基于【尚硅谷新版SSM框架全套视频教程&#xff0c;Spring6SpringBoot3最新SSM企业级开发】https://www.bilibili.com/video/BV1AP411s7D7?vd_sourcea91dafe0f846ad7bd19625e392cf76d8 总结 资料获取网址&#xff1a;https://www.wolai.com/v5Kuct5ZtPeVBk4NBUGBWF 框架…

docker-network

docker_network手册 一、docker 1.常见指令 在 Docker 环境中&#xff0c;网络是实现容器之间以及容器与外部世界通信的关键部分。不同的网络设置可以满足不同的应用场景需求。 这个参数用于指定容器运行时所连接的网络。通过指定特定的网络&#xff0c;可以控制容器的网络隔…

Maven教程——从入门到入坑

第1章 为什么要使用Maven 1.1 获取第三方jar包   开发中需要使用到的jar包种类繁多&#xff0c;获取jar包的方式都不尽相同。为了查找一个jar包找遍互联网&#xff0c;身心俱疲。不仅如此&#xff0c;费劲心血找到的jar包里有的时候并没有你需要的那个类&#xff0c;又或者有…

前端JS常见面试题

数据双向绑定 Bug解决 集成工作涉及 版本node 依赖包报错 版本问题&#xff01;&#xff01;&#xff01;ElementUI、Cesium、ant-design 配置、代码和其他 混入 在Vue中&#xff0c;混入&#xff08;Mixins&#xff09;是一种非常有用的功能&#xff0c;它允许你创建可复…

DAY13信息打点-Web 应用源码泄漏开源闭源指纹识别GITSVNDS备份

#知识点 0、Web架构资产-平台指纹识别 1、开源-CMS指纹识别源码获取方式 2、闭源-习惯&配置&特性等获取方式 3、闭源-托管资产平台资源搜索监控 演示案例&#xff1a; ➢后端-开源-指纹识别-源码下载 ➢后端-闭源-配置不当-源码泄漏 ➢后端-方向-资源码云-源码泄漏 …

你们准备好了吗?Python 入行 AI 的基础技术栈及学习路线

人工智能&#xff08;AI&#xff09;是当今技术发展的重要领域之一&#xff0c;而 Python 已成为 AI 领域的首选编程语言之一。Python 简单易学&#xff0c;具有丰富的生态系统和社区支持&#xff0c;特别是在 AI 和机器学习&#xff08;ML&#xff09;领域有大量强大的库和框架…

研1日记9

1.理解conv1d和conv2d a. 1和2处理的数据不同&#xff0c;1维数据和图像 b. 例如x输入形状为(32,19,512)时&#xff0c;卷积公式是针对512的&#xff0c;而19应该变换为参数中指定的输出通道。 2.“SE块”&#xff08;Squeeze-and-Excitation Block&#xff09;它可以帮助模…

Vue 中 watch 和 watchEffect 的区别

watch 和 watcheffect 都是 vue 中用于监视响应式数据的 api&#xff0c;它们的区别在于&#xff1a;watch 用于监视特定响应式属性并执行回调函数。watcheffect 用于更通用的响应式数据监视&#xff0c;但回调函数中不能更新响应式数据。Vue 中 watch 和 watchEffect 的区别 …

jdk8,jdk11环境变量

Classpath &#xff1a;.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; path : %JAVA_HOME%\jre\bin %JAVA_HOME%\bin java_home: java根目录 jdk11环境变量配置

【论文阅读】Face2Diffusion for Fast and Editable Face Personalization

code&#xff1a;mapooon/Face2Diffusion: [CVPR 2024] Face2Diffusion for Fast and Editable Face Personalization https://arxiv.org/abs/2403.05094 (github.com) 论文 介绍 面部个性化旨在将从图像中获取的特定面部插入到预先训练的文本到图像扩散模型中。然而&#…

TulingMember进销存系统

TulingMember 介绍 使用.net6,基于 Furion +viewui开发的一套极简的进销存管理系统。 技术栈 sqlserver2019redisvueC#语言功能点 角色权限商品管理销售单采购单库存盘点财务记账打印审计日志预留saas字段,可自行拓展多租户。使用说明 需要了解furion框架,文档地址:http…

【2023年】云计算金砖牛刀小试3

A场次题目:OpenStack平台部署与运维 业务场景: 某企业拟使用OpenStack搭建一个企业云平台,用于部署各类企业应用对外对内服务。云平台可实现IT资源池化,弹性分配,集中管理,性能优化以及统一安全认证等。系统结构如下图: 企业云平台的搭建使用竞赛平台提供的两台云服务…

看这篇告诉你Spring如何完美的解决循环依赖

创作内容丰富的干货文章很费心力&#xff0c;感谢点过此文章的读者&#xff0c;点一个关注鼓励一下作者&#xff0c;激励他分享更多的精彩好文&#xff0c;谢谢大家&#xff01; 循环依赖&#xff0c;其实就是循环引用&#xff0c;就是两个或者两个以上的 bean 互相引用对方&am…

Kafka【十一】数据一致性与高水位(HW :High Watermark)机制

【1】数据一致性 Kafka的设计目标是&#xff1a;高吞吐、高并发、高性能。为了做到以上三点&#xff0c;它必须设计成分布式的&#xff0c;多台机器可以同时提供读写&#xff0c;并且需要为数据的存储做冗余备份。 图中的主题有3个分区&#xff0c;每个分区有3个副本&#xf…

浅谈C#之线程创建和管理

一、基本介绍 线程是一种并发执行的机制&#xff0c;允许程序同时执行多个任务。线程的使用使得我们能够利用计算机的多核处理器&#xff0c;实现程序的并行执行&#xff0c;提高系统的性能和响应能力。本文将详细介绍C#中线程的定义和使用方法&#xff0c;涵盖线程的创建、启动…

微模块冷通道动环监控:智能化数据中心管理利器@卓振思众

在现代数据中心和机房管理中&#xff0c;微模块冷通道动环监控系统的引入&#xff0c;标志着对冷却和环境管理的新纪元。这一系统不仅提升了数据中心的运维效率&#xff0c;还对设备的安全性和稳定性提供了强有力的保障。本文将详细探讨微模块冷通道动环监控的功能和其在数据中…

HPM6E00:PWM V2使用指南

先楫推出的HPM6E00系列芯片&#xff0c;PWM功能升级到了V2版本。和V1版本不同的是&#xff0c;V2版本的每组PWM模块包含4个独立的PWM生成模块&#xff0c;每个PWM生成模块包含一个counter和4个比较器&#xff0c;可以生成4组频率不同的PWM波。每个PWM生成模块&#xff0c;对应生…

wordpress建立数据库连接失败 数据库删除恢复

查遍一整天&#xff0c;终于找到解决办法。 问题 wordpress登录突然显示建立数据库连接失败。 解决办法 办法一 通用的解决办法就是网上一大堆的核对conf文件的配置对不对&#xff0c;数据库连接对不对什么的&#xff0c;网上到处都是。 但是我都试过后&#xff0c;还核对…