Leetcode 215 数组中的第K个最大元素

Leetcode 215: 数组中的第K个最大元素 是一道非常经典的数组排序与查找问题,也是面试中非常常见的问题。考察重点包括:排序、堆排序、快速选择等多种方法,其中需要快速定位第K个最大元素。


问题描述

  • 给定一个未排序的数组 nums,要求返回其中第 k 个最大的元素。
  • 注意,第 k 大的元素是按降序排列的第 k 个元素。

示例输入输出

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

解法 1:排序

思路

  • 最简单直接的方法是对数组进行排序,然后返回第 k 大的元素。
  • 将数组按降序排序,第 k 大的元素就是索引为 k-1 的元素。

代码模板

import java.util.Arrays;class Solution {public int findKthLargest(int[] nums, int k) {Arrays.sort(nums); // 默认是升序排列return nums[nums.length - k]; // 倒数第 k 个就是第 k 大}
}

复杂度分析

  • 时间复杂度: O(n log n)
    • 使用排序算法对数组排序,最小复杂度为 O(n log n)(如快速排序、归并排序)。
  • 空间复杂度: O(1) (如果使用就地排序),或 O(n) (如果使用额外空间的排序算法)。

适用场景

  • 当数据量较小(如 n < 1000)时可以快速实现,易于理解和写出。
  • 面试时作为最基础的解法,可以先写出来确保正确性。

解法 2:堆排序 (使用最小堆)

思路

  1. 最小堆可以维护一个包含 k 个元素的小顶堆,其中堆顶元素始终为当前堆中最小的元素。

    • 遍历数组。
    • 对于当前元素:
      • 如果堆大小小于 k,直接将元素加入堆。
      • 如果堆已经满,并且当前元素大于堆顶元素,则将堆顶元素替换为当前元素,并调整堆。
  2. 遍历完成后,堆顶元素就是第 k 大的元素。


代码模板

import java.util.PriorityQueue;class Solution {public int findKthLargest(int[] nums, int k) {// 初始化一个最小堆,容量为 kPriorityQueue<Integer> heap = new PriorityQueue<>(k);// 遍历数组for (int num : nums) {if (heap.size() < k) {heap.offer(num); // 如果堆未满,直接加入} else if (num > heap.peek()) {heap.poll(); // 弹出最小值heap.offer(num); // 加入当前元素}}// 返回堆顶元素return heap.peek();}
}

复杂度分析

  • 时间复杂度: O(n log k)
    • 遍历数组需要 O(n),每次堆的插入与删除操作需要 O(log k)。
  • 空间复杂度: O(k)
    • 堆中只存储 k 个元素。

适用场景

  • 数据量较大,但 k 值较小,适合用堆来优化。
  • 中等规模数据场景的高效解决方案。

解法 3:快速选择 (Quickselect)

思路

  1. 快速选择是快速排序的变种,只关注目标元素所在的部分,不需要对整个数组完全排序。

    • 随机选择一个枢轴 (pivot);
    • 将数组分区,使 pivot 左侧的元素都小于 pivot,右侧的元素都大于 pivot;
    • 判断 pivot 的位置:
      • 如果 pivot 恰好是第 n-k 大元素,则直接返回;
      • 如果 pivot 在第 n-k 的右侧,则在左半部分递归;
      • 如果 pivot 在第 n-k 的左侧,则在右半部分递归。
  2. 递归实现快速选择。


代码模板

import java.util.Random;class Solution {public int findKthLargest(int[] nums, int k) {int n = nums.length;return quickSelect(nums, 0, n - 1, n - k);}private int quickSelect(int[] nums, int left, int right, int index) {// 分区操作int pivot = partition(nums, left, right);if (pivot == index) {return nums[pivot]; // 找到结果} else if (pivot < index) {return quickSelect(nums, pivot + 1, right, index);} else {return quickSelect(nums, left, pivot - 1, index);}}private int partition(int[] nums, int left, int right) {int pivot = nums[right]; // 选择最右侧元素为枢轴int i = left - 1;        // i 指向比 pivot 小的区域的最后一个元素for (int j = left; j < right; j++) {if (nums[j] <= pivot) { // 把小于等于 pivot 的元素交换到左侧i++;swap(nums, i, j);}}swap(nums, i + 1, right);return i + 1; // 返回 pivot 的最终位置}private void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}

复杂度分析

  • 平均时间复杂度: O(n)
    • 快速选择对每次迭代部分划分,平均情况下不断减少搜索范围。
  • 最坏时间复杂度: O(n²)
    • 在极端情况下(如总是选择不平衡的 pivot),时间复杂度退化为 O(n²)。
  • 空间复杂度: O(1)
    • 原地分区,不占用额外空间。

适用场景

  • 当需要更高效的数据操作,而数据量较大时,非常适合快速选择。
  • 均值场景下效率优于排序和堆。

解法 4:使用内置库

思路

  • 使用 Java 的内置库,如 Arrays.sortPriorityQueue,快速获取目标元素。

代码模板

import java.util.Collections;
import java.util.PriorityQueue;class Solution {public int findKthLargest(int[] nums, int k) {PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());for (int num : nums) {maxHeap.add(num);}for (int i = 1; i < k; i++) {maxHeap.poll();}return maxHeap.poll();}
}

快速 AC 策略

  1. 首选快速选择 (Quickselect, 解法 3)

    • 平均时间复杂度 O(n),适合处理大规模数据。
    • 适合面试或比赛中优先编写,凸显算法能力。
  2. 堆排序 (解法 2)

    • O(n log k) 的效率,适合 k 较小的场景。
    • 实现简单,非常稳定。
  3. 排序 (解法 1)

    • 简单易实现,适合快速验证结果或小规模数据。

根据场景选择合适解法,可以快速 AC 本题!

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

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

相关文章

一键安装Nginx部署脚本之Linux在线安装Nginx,脚本化自动化执行服务器部署(附执行脚本下载)

相关链接 一键安装Nginx部署脚本之Linux在线安装Nginx一键安装Redis部署脚本之Linux在线安装Redis一键安装Mysql部署脚本之Linux在线安装Mysql一键安装JAVA部署脚本之Linux在线安装JDKXshell客户端免费版无需注册XFtp客户端免费版无需注册 前言 简化服务器部署操作&#xff0…

反向代理以及其使用场景

一、反向代理概念 反向代理(Reverse Proxy)是一种服务器配置,它将客户端的请求转发给内部的另一台或多台服务器处理,然后将响应返回给客户端。与正向代理(Forward Proxy)不同,正向代理是客户端的代理,客户端将请求发送到代理服务器,再由代理服务器访问目标服务器;而…

Linux网络 NAT、代理服务、内网穿透

NAT 技术 IPv4 协议中存在 IP 地址数量不充足的问题&#xff0c;而 NAT 技术是当前解决 IP 地址不够用的主要手段 , 是路由器的一个重要功能。NAT 能够将私有 IP 对外通信时转为全局 IP&#xff0c;也就是就是一种将私有 IP 和全局 IP 相互转化的技术方法。 这可以让很多学…

广义线性模型下的数据分析(R语言)

一、实验目的&#xff1a; 通过上机试验&#xff0c;掌握利用R实现线性回归分析、逻辑回归、列联分析及方差分析&#xff0c;并能对分析结果进行解读。 数据&#xff1a; 链接: https://pan.baidu.com/s/1JqZ_KbZJEk-pqSUWKwOFEw 提取码: hxts 二、实验内容&#xff1a; 1、2…

Windows环境下Maven的配置

Windows环境下Maven的配置 一、Maven下载 Maven官网地址 apache-maven-3.8.8-bin.zip 二、安装和配置 解压到本地目录&#xff0c;例如&#xff1a;D:\software\apache-maven-3.8.8 新建变量MAVEN_HOMED:\software\apache-maven-3.8.8&#xff08;以自己的安装路径为准&…

Spring MVC 处理请求

目录 1、SpringMVC 处理请求1.1、HTTP 请求报文1.2、获取 URL 中参数 PathVariable1.3、获取请求头数据1.3.1、传统获取 Header/Cookie1.3.2、获取 Header—RequestHeader1.3.3、获取 Cookie—CookieValue1.3.4、Session 的存储和获取—SessionAttribute 1.4、获取请求数据1.4.…

OpenAI 最后一代非推理模型:OpenAI 发布 GPT-4.5预览版

最后一代非推理大模型 在人工智能领域&#xff0c;OpenAI 一直以其创新的技术和卓越的产品引领着行业的发展。近期&#xff0c;OpenAI 正式发布了 GPT-4.5 研究预览版。不仅如此&#xff0c;官方还宣称 GPT-4.5 被定位为 “最后一代非推理模型”&#xff0c;这一消息再次引起了…

什么是JTAG、SWD?

一、什么是JTAG&#xff1f; JTAG&#xff08;Joint Test Action Group&#xff0c;联合测试行动小组&#xff09;是一种国际标准测试协议&#xff0c;常用于芯片内部测试及对系统进行调试、编程等操作。以下从其起源、工作原理、接口标准、应用场景等方面详细介绍&#xff1a…

知识周汇|SAP脚本自动化-淋过雨的人更懂得伞的价值

目录 摘要 1 知识概览 1.1SAP GUI脚本 1.2Tracker工具 2 实践案例 2.1步骤1&#xff1a;SAP启动并进入系统&#xff08;文本关键&#xff09; 2.1.1手动操作&#xff1a;鼠标双击SAP&#xff0c;并点击所需要系统 2.1.2代码实现 2.2步骤2&#xff1a;通过tracker完善后…

【GPU使用】如何在物理机和Docker中指定GPU进行推理和训练

我的机器上有4张H100卡&#xff0c;我现在只想用某一张卡跑程序&#xff0c;该如何设置。 代码里面设置 import os # 记住要写在impot torch前 os.environ[CUDA_VISIBLE_DEVICES] "0, 1"命令行设置 export CUDA_VISIBLE_DEVICES0,2 # Linux 环境 python test.py …

【无标题】ABP更换MySql数据库

原因&#xff1a;ABP默认使用的数据库是sqlServer&#xff0c;本地没有安装sqlServer&#xff0c;安装的是mysql&#xff0c;需要更换数据库 ABP版本&#xff1a;9.0 此处以官网TodoApp项目为例 打开EntityFrameworkCore程序集&#xff0c;可以看到默认使用的是sqlServer&…

【网络编程】之TCP实现客户端远程控制服务器端及断线重连

【网络编程】之TCP实现客户端远程控制服务器端及断线重连 TCP网络通信实现客户端简单远程控制主机基本功能演示通信过程代码实现服务器模块执行命令模块popen系列函数 客户端模块服务器主程序 windows作为客户端与服务器通信#pragma comment介绍 客户端使用状态机断线重连代码实…

Git快速入门

文章目录 Git简介准备工作常用的Linux命令git配置 git工作原理git项目创建和克隆git基本操作命令git忽略文件配置ssh远程连接 IDEA集成Gitgit分支&#xff08;多人开发&#xff09;公司中用到的&#xff08;很清楚&#xff09; Git 简介 Git就是版本控制的工具 下面这个叫手动…

Redis 的几个热点知识

前言 Redis 是一款内存级的数据库&#xff0c;凭借其卓越的性能&#xff0c;几乎成为每位开发者的标配工具。 虽然 Redis 包含大量需要掌握的知识&#xff0c;但其中的热点知识并不多。今天&#xff0c;『知行』就和大家分享一些 Redis 中的热点知识。 Redis 数据结构 Redis…

深入解析Java虚拟机(JVM)的核心组成

深入解析Java虚拟机&#xff08;JVM&#xff09;的核心组成 Java虚拟机&#xff08;JVM&#xff09;作为Java语言跨平台的核心实现&#xff0c;其架构设计精妙而复杂。理解JVM的组成部分&#xff0c;是掌握Java内存管理、性能调优和问题排查的关键。本文将从四大核心模块剖析J…

GIT工具学习【2】:分支

1.什么是分支 新建一个分支&#xff0c;可以认为把当前项目copy了一份&#xff0c;不太严谨&#xff0c;没毛病&#xff0c;里面虽然文件内容和名字相同&#xff0c;其实互相没有关系。 2.什么是合并分支 就是把两个分支&#xff08;项目文件夹&#xff09;合并在一起 git m…

40岁开始学Java:Java中单例模式(Singleton Pattern),适用场景有哪些?

在Java中&#xff0c;单例模式&#xff08;Singleton Pattern&#xff09;用于确保一个类只有一个实例&#xff0c;并提供全局访问点。以下是详细的实现方式、适用场景及注意事项&#xff1a; 一、单例模式的实现方式 1. 饿汉式&#xff08;Eager Initialization&#xff09; …

Linux常见基本指令(一)

目录 前言 1、ls指令 2、用户相关指令 3、pwd指令 4、cd指令 相对路径与绝对路径 5、创建、删除文件和目录相关的指令 创建相关的指令 删除相关的指令 6、拷贝、移动和重命名 cp指令 mv指令 前言 学习Linux的过程中一定要多自己动手&#xff0c;Linux的指令繁多&a…

测试金蝶云的OpenAPI

如何使用Postman测试K3Cloud的OpenAPI 1. 引言 在本篇博客中&#xff0c;我将带你逐步了解如何使用Postman测试和使用K3Cloud的OpenAPI。内容包括下载所需的SDK文件、配置文件、API调用及测试等步骤。让我们开始吧&#xff01; 2. 下载所需的SDK文件 2.1 获取SDK 首先&…

Tomcat

1.Tomcat是什么&#xff1f; Tomcat 是一个开源的、轻量级的 Servlet 容器&#xff0c;也被称为 Web 服务器&#xff0c;由 Apache 软件基金会的 Jakarta 项目开发&#xff0c;在 Java Web 开发领域应用广泛。 1&#xff09;Servlet 容器&#xff1a;Servlet 是 Java 语言编写…