题目

https://leetcode.com/problems/kth-largest-element-in-an-array/


题解

本题需要建立大顶堆。关于堆的数据结构,需要知道:

什么是堆?

是一棵 完全二叉树:即使它不是满二叉树,也是正在从左往右变满的过程中。

1)堆结构就是用数组实现的完全二叉树结构

2)完全二叉树中,如果每棵子树的 最大值都在顶部,是 大根堆

3)完全二叉树中,如果每棵子树的 最小值都在顶部,是 小根堆

4)堆结构的 heapInsert 与 heapify 操作

5)堆结构的增大和减少

6)优先级队列结构,就是堆结构

7)特点:由 N 个数 组成的堆,高度是 log(n)

如何用数组存放堆?

如果从 0 位置开始:

i 层,则

  • 左孩子:2 * i + 1
  • 右孩子:2 * i + 2
  • 父节点:(i - 1) / 2
如果从 1 位置开始:

正是由于可以使用 位运算 来代替 算数运算,效率更高,所以有时候让下标从 1 开始。

  • 左孩子:2 * i (i << 1)
  • 右孩子:2 * i + 1 (i << 1 | 1)
  • 父节点:i / 2 (i >> 1)

如何将数组转化成大根堆?—— heapInsert 操作

每在 i 位置加入一个新的节点,都与它的 (i - 1) / 2 位置的父节点比较,如果比父节点大,则交换(并while比较父节点与父父节点)

private void heapInsert(int[] arr, int index) {while (arr[index] > arr[(index - 1) / 2]) {swap(arr, index, (index - 1) / 2);index = (index - 1) / 2;}
}
private void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;
}

如何返回并删除大根堆的最大值,剩余数字依然保持大根堆?—— heapify 操作

  1. 将顶部元素取出
  2. 将大根堆的最后位置上的元素覆盖到顶部
  3. while 循环
    1. 如果左右孩子中较大的数比当前节点更大,则交换当前节点和较大的孩子节点
    2. 如果左孩子下标越界,或左右孩子都不比当前节点大,就停止
// 返回最大值,并在大根堆中把最大值删掉,剩下的数依然保持大根堆形态
public int pop() {int ans = heap[0];swap(heap, 0, --heapSize);heapify(heap, 0, heapSize);return ans;
}
// 从index位置开始,不断的下沉,直到我的孩子都不再比我大,或者我已经没孩子了,就停止
private void heapify(int[] arr, int index, int heapSize) {int left = index * 2 + 1;while (left < heapSize) {// largest存储左右孩子 较大者 的下标int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;// largest存储两个孩子与父节点 较大者 的下标largest = arr[largest] > arr[index] ? largest : index;if (largest == index) { // 不需要交换的情况break;}swap(arr, largest, index);index = largest;left = index * 2 + 1;}
}

堆排序

  1. 先让整个数组都变成大根堆结构,建立堆的过程:

    1. 从上到下的方法,时间复杂度为O(N*logN)
    2. 从下到上的方法,时间复杂度为O(N)
  2. 把堆的最大值和堆末尾的值交换,然后减少堆的大小之后,再去调整堆,一直周而复始,时间复杂度为O(N*logN)
  3. 堆的大小减小成0之后,排序完成!
public static void heapSort(int[] arr) {if (arr == null || arr.length < 2) {return;}// 方法1:对数组进行堆排序 O(N*logN)for (int i = 0; i < arr.length; i++) { // O(N)heapInsert(arr, i); // O(logN)}// 方法2:仅将数组转化成大顶堆 O(n) for (int i = arr.length - 1; i >= 0; i--) {heapify(arr, i, arr.length);}
}

本题代码

class Solution {int[] nums;int heapSize;public int findKthLargest(int[] nums, int k) {this.nums = nums;this.heapSize = nums.length;// 先让整个数组变成大根堆结构// 方法1:从上至下 对数组进行堆排序 O(N*logN)
//        for (int i = 0; i < nums.length; i++) // O(N)
//            heapInsert(nums, i); // O(logN)// 方法2:从下至上 仅将数组转化成大顶堆 O(N)for (int i = nums.length - 1; i >= 0; i--)heapify(nums, i, nums.length);int result = -1;for (int i = 0; i < k; i++)result = pop();return result;}public int pop() {int max = nums[0];swap(nums, 0, --heapSize);heapify(nums, 0, heapSize);return max;}// 方法1 从上至下调整堆:每在i位置加入一个新的节点,都与它的(i-1)/2位置的父节点比较,如果比父节点大,则交换(并while比较父节点与父父节点)private void heapInsert(int[] arr, int index) {while (arr[index] > arr[(index - 1) / 2]) {swap(arr, index, (index - 1) / 2);index = (index - 1) / 2;}}// 方法2 从下至上调整堆:从index位置开始,不断的下沉,直到我的孩子都不再比我大,或者我已经没孩子了,就停止public void heapify(int[] arr, int i, int heapSize) {int left = i * 2 + 1;while (left < heapSize) {int largest = left + 1 < heapSize && nums[left + 1] > nums[left] ? left + 1 : left; // 左右孩子较大者的下标largest = nums[largest] > nums[i] ? largest : i; // 两个孩子与父节点较大者的下标if (largest == i) break; // 不需要交换的情况swap(arr, largest, i);i = largest; // 更新i使其下沉left = 2 * i + 1;}}private void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}
}

leetcode 215. Kth Largest Element in an Array | 215. 数组中的第K个最大元素(Java)相关推荐

  1. 剑指offer 最小的k个数 leetcode 215. Kth Largest Element in an Array

    注意multiset的一个bug: multiset带一个参数的erase函数原型有两种.一是传递一个元素值,如上面例子代码中,这时候删除的是集合中所有值等于输入值的元素,并且返回删除的元素个数:另外 ...

  2. 网易2016 实习研发工程师 [编程题]寻找第K大 and leetcode 215. Kth Largest Element in an Array...

    传送门 有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数. 给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在. 测试样例: [1,3,5, ...

  3. [swift] LeetCode 215. Kth Largest Element in an Array

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  4. [leedcode 215] Kth Largest Element in an Array

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  5. 215. Kth Largest Element in an Array 数组中的第K个最大元素

    Title 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 ...

  6. LeetCode 215 Kth Largest Element in an Array

    思路: 跟找第kth小的数相反,数组逆向排序.从前找第k - 1个数. 1 public class Solution { 2 public int findKthLargest(int[] arra ...

  7. leetcode之Kth Largest Element in an Array

    这题是求出来排序好的数的第k个大的数.用了.sort()之后就非常简单了.不用自己排序的表示真是简单啊.然而真讲排序我还基本不会...代码如下: class Solution(object):def ...

  8. 力扣215:数组中的第K个最大元素 (leetcode 215:Kth Largest Element In An Array)

    题目链接:https://leetcode.cn/problems/kth-largest-element-in-an-array 目录: 一.题目描述 1.中文 2.英文 二.解决方法 1.直接排序 ...

  9. LeetCode 215. Kth Largest Element in an Array--数字第K大的元素--最大堆或优先队列--C++,Python解法

    题目地址:Kth Largest Element in an Array - LeetCode Find the kth largest element in an unsorted array. N ...

最新文章

  1. 60秒计时器的仿真电路_物联网应用基于Arm微控制器的低功耗定时关机计时器
  2. PHP怎么做一个加法口诀,神奇的手指速算口诀,100以内的加减法一分钟学会
  3. mysql pmod项目_内置函数 - 数学函数 - 《Apache Doris 文档(201812)》 - 书栈网 · BookStack...
  4. python导入xlrd库_python中xlrd库如何实现文件读取?
  5. 如何进行cad地理配准_【教程】自带高度建筑轮廓如何制作分色图
  6. DMSP/OLS夜间灯光数据
  7. SQL Server 各版本密钥
  8. 哈工大本部2022形式语言与自动机期末试题
  9. 如何提高服务器网站访问速度,如何有效提升网站打开速度?
  10. HEVC解码器HM源码阅读(二)解码器中类的介绍
  11. MTK AF Tuning Preparation项目
  12. 岁月安好,不存在的!不过是有人替你负重前行
  13. 靶机渗透练习43-Lord Of The Root
  14. android开发(43) 动画演示,会跑的小人,从屏幕左侧跑到右侧
  15. Rhel 7.3 基本操作
  16. Z-BlogPHP蓝色简约风格网址收录导航网站模板
  17. Scanpy Umap 3D
  18. oracle rman备份时间点,Oracle Rman 控制RMAN的备份时间,减少IO消耗
  19. php 不恒等,Re: 弱问:Latex里不恒等号(三横一撇) - 精华区 - 数学科学学院(SMS)版 - 北大未名BBS...
  20. 2022年最新版的运维面试题【从基础到精通】

热门文章

  1. HDU - 1796 How many integers can you find(容斥原理)
  2. POJ - 1201 Intervals(差分约束+最短路)
  3. uva1624knots
  4. php tp框架调用方法,thinkPHP框架使用方法
  5. L1-036. A乘以B
  6. BZOJ2806(后缀自动机+DP)
  7. [51nod1847][算法马拉松23(飞越愚人节)F]奇怪的数学题
  8. 《openssl编程》之配置文件
  9. 基于WSAAsyncSelect模型实现的聊天室图形客户端
  10. 精美技术图赏-技术精华|二期