【一起刷LeetCode】在未排序的数组中找到第 k 个最大的元素
题目描述
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
题解
根据问题的描述其实我们很容易想到先排序再取第k个值, 这种方式也就是我们俗称的暴力求解法。
暴力求解法
思路分析:
数组排序后的第k个最大元素,举例说明一下:
数组一共有5个元素时,找第2大,索引值是3;找第4大,索引值是1;根据这个逻辑我们可以推导出,数组升序排序以后,结果元素的索引值是数组长度减去k的值。
代码示例:
public static int findKthLargest(int[] nums, int k) {
int len = nums.length;
Arrays.sort(nums);
return nums[len - k];
}
复杂度分析:
- 时间复杂度:O(N log N), 这里直接使用Arrays.sort(nums);将数据排序,大家都知道jdk默认使用的是快速排序,快速排序的平均时间复杂度是O(N log N)。
- 空间复杂度:O(1),因为是原地排序,没有用到外部辅助空间。
暴力求解法(升级版)
思路分析:
根据暴力求解法中用的快排思路,其实我可以对快排做近一步升级,首先我们随机选择一个元素,并在线性时间内找到其对应在数组中的位置,这样数组就被分成了两部分,一部分是小于元素值的部分,一部分是大于元素值的部分,这时我们在比较这个元素与k的大小来决定我们在那一部分数组继续做快速排序。这种思路其实就是快速排序中partition(切分)的操作。
每次partition操作总能排定一个元素,还能够知道这个元素它在数组中的最终位置,然后我们在根据partition后的结果来减少范围,这样的思想叫做“减而治之”。
代码示例:
public static int findKthLargest(int[] nums, int k) {
int leng = nums.length;
int left = 0;
int right = leng - 1;
int target = leng - k;
return quickSelect(nums, left, right, target);
}
/**
* 排序
* @param nums
* @param left
* @param right
* @param target
* @return
*/
public static int quickSelect(int[] nums, int left, int right, int target) {
if (left == right) {
return nums[left];
}
//随机选择一个
Random random = new Random();
int pivot = left + random.nextInt(right - left);
pivot = partition(nums, left, right, pivot);
if (target == pivot) {
return nums[target];
}
if (target < pivot) {
return quickSelect(nums, left, pivot - 1, target);
}
return quickSelect(nums, pivot + 1, right, target);
}
/**
* partition切分
* @param nums
* @param left
* @param right
* @param target
* @return
*/
private static int partition(int[] nums, int left, int right, int target) {
int pivot = nums[target];
swap(nums, target, right);
int j = left;
for (int i = left; i <= right; i++) {
if (nums[i] < pivot) {
swap(nums, j, i);
j++;
}
}
swap(nums, j, right);
return j;
}
/**
* 交换
* @param nums
* @param a
* @param b
*/
public static void swap(int[] nums, int a, int b) {
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
复杂度分析:
- 时间复杂度:平均情况O(N), 最坏情况O($N^2$).
- 空间复杂度:O(1).
- 写作不易,转载请注明出处,喜欢的小伙伴可以关注公众号查看更多喜欢的文章。
- 联系方式:4272231@163.com
- QQ:95472323
- 微信:ffj2000
【一起刷LeetCode】在未排序的数组中找到第 k 个最大的元素的更多相关文章
- 在未排序的数组中找到第 k 个最大的元素
在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 ...
- leetcode.排序.215数组中的第k个最大元素-Java
1. 具体题目 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 : 输入: [3,2,1,5,6,4] 和 k = ...
- [程序员代码面试指南]第9章-在两个长度相等的排序数组中找到第k小的数(二分)
题目 给定两个有序数组arr1和arr2,再给定一个整数k,返回所有的数中第k小的数. 题解 利用题目"在两个长度相等的排序数组中找到第上中位数"的函数 分类讨论 k < 1 ...
- 算法总结之 在两个排序数组中找到第K小的数
给定两个有序数组arr1 和 arr2 ,再给定一个int K,返回所有的数中第K小的数 要求长度如果分别为 N M,时间复杂度O(log(min{M,N}),额外空间复杂度O(1) 解决此题的方法跟 ...
- LeetCode题解 | 215. 数组中的第K个最大元素
在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 ...
- LeetCode:数组中的第K个最大元素【215】
LeetCode:数组中的第K个最大元素[215] 题目描述 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: ...
- [LeetCode]215. 数组中的第K个最大元素(堆)
题目 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出 ...
- 数组中的第K个最大元素leetcode(Top K的问题)
在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 ...
- Leetcode 215. 数组中的第K个最大元素 By Python
在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 ...
随机推荐
- Web基础了解版03-jQuery
jQuery jQuery,顾名思义,也就是JavaScript和查询(Query)极大地简化了JavaScript开发人员遍历HTML文档.操作DOM.处理事件.执行动画和开发Ajax. jQuer ...
- GoLand不同目录(包)方法调用
新手学go,跨目录调用方法是真的难,弄了好几天,几乎要放弃go了,在此演示一下如何跨目录(包)调用~ 需求是main.go调用model包下mysql.go中Query方法,目录结构如下. 要点: 1 ...
- NodeJS3-4基础API----fs(文件系统)
异步的形式总是将完成回调作为其最后一个参数. 传给完成回调的参数取决于具体方法,但第一个参数始终预留用于异常. 如果操作成功完成,则第一个参数将为 null 或 undefined. 1.读取文件操作 ...
- JS基础知识——变量类型和计算(一)
JS中使用typeof能得到的哪些类型? 何时使用===何时使用==? JS中有哪些内置函数? JS变量按照存储方式区分为哪些类型,描述其特点? 如何理解JSON? 知识点梳理 一.变量类型: (1) ...
- shell概述与echo命令
一.Shell概述 1.什么是shell? 由此可见shell是用户与系统进行交互的接口,通过执行各种命令来完成时间处理与调度. 2.shell分类 Shell类别 易学性 可移植性 编辑性 快捷性 ...
- C#线程学习笔记八:async & await入门一
一.涉及内容 async & await是C# 5.0引入的,控制台输出所使用的$符号(拼接字符串)是C# 6.0引入的,其功能类似于string.Format()方法. 二.多线程.异步.同 ...
- c++-继承的学习
继承的基本概念 继承和派生 继承概念 派生类的访问控制(继承三种方式.类三种访问控制.三看原则)综合训练 继承中的构造和析构 类型兼容性原则 继承中的构造和析构 继承中同名成员函数.成员变量处理方法 ...
- zabbix服务深入
第1章 Grafana自定义图形 1.安装grafana [root@m01 /data/soft]# wget https://dl.grafana.com/oss/release/grafana- ...
- MQ报错2009/2085解决方法
1.1. 响应2009错误 1.1.1. 涉及协议 MQ,调试回放阶段 1.1.2. 错误信息 完成码2原因为2009 1.1.3. 可能原因 远端MQ连接数不足,拒绝连接 1.1.4. ...
- luoguP4449 于神之怒加强版
题意 默认\(n\leqslant m\). 一波莫反后可得: \(\sum\limits_{T=1}^{n}\frac{n}{T}\frac{m}{T}\sum\limits_{d|T}d^k\mu ...