CodeTop之数组中的第K个最大的元素

题目链接

215. 数组中的第K个最大元素 - 力扣(LeetCode)

题目解析

算法原理

解法一:

直接理由java内部的排序函数,Arrays.sort()进行排序, 然后我们直接返回第k个最大的元素

nums[nums.length-k]

解法二:

使用堆

我们先把所有元素丢到大根堆里面,然后取k次堆顶元素

PriorityQueue<Integer> heap = new PriorityQueue<>((a,b)->b-a);

解法三: 

三指针法, 数组分三块

代码编写

解法一:

class Solution {public int findKthLargest(int[] nums, int k) {// 排序Arrays.sort(nums);return nums[nums.length - k];}
}

解法二:

class Solution {public int findKthLargest(int[] nums, int k) {// 利用大根堆PriorityQueue<Integer> heap = new PriorityQueue<>((a,b)-> b-a);// 把元素放进大根堆for(int x : nums){heap.offer(x);}// 取第k个while(--k != 0){heap.poll();}return heap.poll();}
}

解法三

class Solution {// 交换private static void swap(int[] nums, int index1, int index2) {int tmp = nums[index1];nums[index1] = nums[index2];nums[index2] = tmp;}// 递归,分三段private static int quickSort(int[] nums, int l, int r, int k) {// l, r 是用来固定左右端点的int left = l - 1;int right = r + 1;// 获取区间中间的元素作为 keyint key = nums[(l + r) / 2];  // 修改这里,取中间的值// 数组分成四段// [l,left]<key,[left+1,i]==key,[i+1,right-1]未知,[right,r]>key;int i = l;  // 从区间的开始进行遍历while (i < right) {// 如果是 < keyif (nums[i] < key) {swap(nums, ++left, i++);} else if (nums[i] == key) {// 如果是 == keyi++;} else {// 如果是 > keyswap(nums, --right, i);}}// 此时分成三块: [l, left]<key [left + 1, right - 1]==key [right, r]>key// 分类讨论 [l, left] [left + 1, right - 1] [right, r]int b = (right - 1) - (left + 1) + 1;  // 中间部分的长度int c = r - right + 1;  // [right, r] 部分的长度if (c >= k) {// 去 [right, r] 查找第 k 大return quickSort(nums, right, r, k);} else if ((b + c) >= k) {// 如果中间部分就是第 k 大,直接返回return key;} else {// 去 [l, left] 查找第 k - b - c 大return quickSort(nums, l, left, k - b - c);}}public int findKthLargest(int[] nums, int k) {return quickSort(nums, 0, nums.length - 1, k);}
}

为什么是k-b-c大? 下面是ai的解释
在快速排序(Quick Sort)中,我们通过分区操作将数组分为三部分:

1.小于基准值(key)的部分
2.等于基准值的部分
3.大于基准值的部分

我们希望找到第 k 大的元素。在快速排序的过程中,我们每次选择一个基准值(key)并进行分区,接下来,我们递归地在其中一部分继续查找目标元素。
问题核心
假设我们有一个 k 值,表示我们要找到第 k 大的元素。在分区后,数组被分为三部分:

[l, left] 这部分元素都小于基准值 key
[left + 1, right - 1] 这部分元素等于基准值 key
[right, r] 这部分元素都大于基准值 key

我们已经知道,在这些分区中,key 的位置非常关键。接下来,我们就要根据 k 和这些部分的大小来决定递归的方向。
代码逻辑解释
考虑下面几个变量:

b:等于 key 的元素的个数。
c:大于 key 的元素的个数。

那么,b + c 是右边部分(即大于 key 的部分加上等于 key 的部分)的元素总数。
如果 k 大于 b + c,意味着我们要找的第 k 大的元素不在右边(即大于 key 的部分和等于 key 的部分),而是在左边(小于 key 的部分)。因此,我们递归地去左边查找。
但是,左边的部分有一些特殊情况需要考虑:

左边的部分包含了所有小于 key 的元素,因此找第 k 大的元素时,要跳过这些小于 key 的元素。
1由于已经知道有 b 个元素等于 key,而且右边有 c 个大于 key 的元素,所以我们实际需要在左边找的是第 k - b - c 大的元素。

为什么是 k - b - c

我们已经知道:
c 是大于 key 的元素数量。

b 是等于 key 的元素数量。
因此,如果我们要找的是第 k 大的元素,在递归调用时,要在左边查找的是:
去掉 c 个大于 key 的元素,
去掉 b 个等于 key 的元素,
所以我们要查找的是 第 k - b - c 大的元素。

总结

k 是我们要找的第 k 大的元素。
b 是等于 key 的元素个数。
c 是大于 key 的元素个数。

因此,在左边查找时,我们要寻找的元素是第 k - b - c 大的元素,原因是我们已经排除了右边部分的元素(大于 key 和等于 key 的部分)。

二刷

class Solution {//交换void swap(int[] nums, int index1, int index2) {int tmp = nums[index1];nums[index1] = nums[index2];nums[index2] = tmp;}int quickSort(int[] nums, int l, int r, int k) {// 定义移动边界int left = l - 1;int right = r + 1;int key = nums[(right + left) / 2];// 遍历int i = l;while (i < right) {// 数组分四块if (nums[i] < key) {// 去左边swap(nums, i++, ++left);} else if (nums[i] == key) {// 直接往后走i++;} else {// 去右边swap(nums, i, --right);}}// 此时分为三块:[l,left]<key [left+1,right-1]=key [right,r]>key// 去找第k个最大的元素int b = (right - 1) - (left + 1) + 1; //中间部分int c = r - right + 1; // 右边部分if (c >= k) {// 说明第k个最大在右边部分return quickSort(nums, right, r, k);} else if ((b + c) >= k) {// 说明第k个最大在中间部分return key;} else {// 说明第k个最大在左边部分,调整kreturn quickSort(nums, l, left, k - b - c);}}public int findKthLargest(int[] nums, int k) {// 使用快排来找到数组中第k个最大元素return quickSort(nums, 0, nums.length - 1, k);}
}


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/82849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI任务相关解决方案1-基于NLP的3种模型实现实体识别,以及对比分析(包括基于规则的方法、CRF模型和BERT微调模型)

大家好,我是微学AI,今天给大家介绍一下AI任务相关解决方案1-基于NLP的3种模型实现实体识别,以及对比分析。本文将深入探讨三种不同的命名实体识别(NER)方法,包括基于规则的方法、CRF模型和BERT微调模型,用于识别文本中的地名(LOC)、机构名称(ORG)和人名(PER)实体。通过系统…

IP动态伪装开关

IP动态伪装开关 在OpenWrt系统中&#xff0c;IP动态伪装&#xff08;IP Masquerading&#xff09;是一种网络地址转换&#xff08;NAT&#xff09;技术&#xff0c;用于在私有网络和公共网络之间转换IP地址。它通常用于允许多个设备共享单个公共IP地址访问互联网。以下是关于O…

【MySQL】第10节|MySQL全局优化与Mysql 8.0新增特性详解

全局优化 mysql server参数 1. max_connections&#xff08;最大连接数&#xff09; 含义&#xff1a;MySQL 服务允许的最大并发连接数&#xff08;包括正在使用和空闲的连接&#xff09;。超过此限制时&#xff0c;新连接会被拒绝&#xff08;报错 Too many connections&am…

VS Code 插件 Git History Diff

插件名 进命令行&#xff0c;进Git自己那个分支 查看分支 提交到Git的后想再把另一个也提交到那个分支&#xff0c;用这个命令

Shell脚本中的常用命令

一.设置主机名称 文件设置 文件开机时已读取所以要重新进入 命令更改&#xff08;即使生效&#xff09; 二.网络管理命令 1.查看网卡命令 设置网卡 1&#xff09;DHCP工作模式 2)静态IP 3&#xff09;修改网卡信息 三.简单处理字符 1.打印连续数字 连续打印3个数字 指定打…

C++ 中 std::wstring::c_str() 的潜在风险与安全使用指南

一、问题背景 在开发过程中&#xff0c;我们经常会遇到不同接口之间的数据传递问题。例如&#xff0c;当调用某个接口时&#xff0c;需要传入一个字符串指针作为数据接收的缓冲区&#xff0c;但外围接口使用的是 std::wstring 类型。此时&#xff0c;如果直接将 std::wstring:…

‘js@https://registry.npmmirror.com/JS/-/JS-0.1.0.tgz‘ is not in this registry

解决方法&#xff1a; 1. npm cache clean --force 2.临时切换到官方源 npm config set registry https://registry.npmjs.org/ npm install js0.1.0 npm config set registry https://registry.npmmirror.com/ # 切换回镜像源

ubuntu24 安装MongoDB-6.0.24 数据库操作步骤和配置参数说明

目录 1 下载MongoDB软件 2 操作系统信息 3 MongoDB 软件安装步骤 4 编写mongodb的配置文件 5 生成keyfile 6 使用mongo用户启动mongodb服务 7 设置开机启动(mongo用户) 8 安装MongoDB shell&#xff0c;因为MongoDB-6.0.24 已经移除mongo命令 1 下载MongoDB软件 https:…

单片机——keil5

文章目录 安装教程使用介绍案例展示 接下来进行keil5软件的相关学习使用 安装教程 参考视频链接bilibili 51单片机 大约在8分钟位置处 使用介绍 首先新建project选择对应的芯片型号&#xff08;例如&#xff1a;STC89C52 —— 由于STC系列是国产&#xff0c;keil5软件不支持…

计算机网络相关发展以及常见性能指标

目录 一、因特网概述 1.1 基本概念 1.2 因特网发展的三个阶段 1.3 英特网服务提供者ISP 1.4 英特网的标准化工作 1.5 因特网的组成 1.6 简单总结 二、3种交换方式 2.1 电路交换&#xff08;Circuit Switching&#xff09; 2.2 分组交换&#xff08;Packet Switching&…

Java 面试实录:从Spring到微服务的技术探讨

在一个明亮的会议室里&#xff0c;严肃的面试官与搞笑的程序员谢飞机正进行一场关于Java技术栈的面试。场景设定在一家知名互联网大厂&#xff0c;他们的对话充满了技术性与娱乐性。 第一轮&#xff1a;Spring框架与数据库 面试官&#xff1a;“谢飞机&#xff0c;能解释一下…

OpenCV CUDA模块图像过滤------创建一个 Scharr 滤波器函数createScharrFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数用于创建一个 Scharr 滤波器&#xff08;基于 CUDA 加速&#xff09;&#xff0c;用于图像的一阶导数计算。它常用于边缘检测任务中&#…

yolov8分割任务的推理和后处理解析

文章目录 一、前言二、分割模型的前向推理1. 检测结果&#xff1a;来自Detect类的输出2. 分割结果&#xff08;最终&#xff09;3. 与Detect的主要区别4. 工作流程 三、后处理1. 非极大值抑制&#xff08;NMS&#xff09;过滤检测框2. 分割原型&#xff08;Mask Prototypes&…

4.1.1 Spark SQL概述

Spark SQL是Apache Spark的一个模块&#xff0c;专门用于处理结构化数据。它引入了DataFrame这一编程抽象&#xff0c;DataFrame是带有Schema信息的分布式数据集合&#xff0c;类似于关系型数据库中的表。用户可以通过SQL、DataFrames API和Datasets API三种方式操作结构化数据…

华为OD机试真题——书籍叠放(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 200分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…

尚硅谷redis7 63-69 redis哨兵监控之理论简介

63 redis哨兵监控之理论简介 什么是哨兵 master挂了如何办?从机原地待命。此时数据只能读取不能更新。因此需要&#xff1a; 吹哨人巡查监控后台master主机是否故障,如果故障了根据投票数自动将某一个从库转换为新主库, 哨兵的作用 1、监控redis运行状态,包括master和slave…

word文档格式规范(论文格式规范、word格式、论文格式、文章格式、格式prompt)

文章目录 prompt prompt [格式要求] - 字体&#xff1a;中文宋体小四&#xff1b;英文Times New Roman 12pt&#xff1b;标题黑体 - 行距&#xff1a;1.5倍&#xff08;段前段后0行&#xff09; - 边距&#xff1a;A4默认&#xff08;上下2.54cm&#xff0c;左右3.17cm&…

SpringBoot+tabula+pdfbox解析pdf中的段落和表格数据

一、前言 在日常业务需求中&#xff0c;往往会遇到解析pdf文件中的段落或者表格数据的需求。 常见的做法是使用 pdfbox 来做&#xff0c;但是它只能提取文本数据&#xff0c;没有我们在文件页面上面的那种结构化组织&#xff0c;文本通常是散乱的包含各种换行回车空格等格式&a…

【Elasticsearch】stored_fields

在 Elasticsearch 中&#xff0c;stored_fields 是一个非常重要的概念&#xff0c;主要用于控制文档存储和检索时的行为。以下是对 stored_fields 的详细解释&#xff1a; 1\. stored_fields 的作用 stored_fields 用于指定在检索文档时需要返回的字段。默认情况下&#xff0c;…

计算机网络 | 1.1 计算机网络概述思维导图

附大纲&#xff1a; 计算机网络的概念 一个通过通信设备与线路把不同计算机系统连接起来&#xff0c;实现资源共享和信息传递的系统 计算机网络的组成 从组成成分上 硬件&#xff1a;主机、通信链路、交换设备、通信处理机软件&#xff1a;网络操作系统、聊天软件等协议&…