【算法】堆排之 215.数组中的第K个最大元素(medium)

news/2024/9/28 7:41:45 标签: 算法

 系列专栏

双指针

模拟算法

分治思想


目录

1、题目链接

2、题目介绍

 3、解法

解题思路

排序方法的选择:

构建小堆:

提取第 k 个最大元素:

4、代码


1、题目链接

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

2、题目介绍

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

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

示例 2:

输入:

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

提示:

1 <= k <= nums.length <= 105

-104 <= nums[i] <= 104

 3、解法

解题思路

  1. 排序方法的选择

    • 虽然直观上可能会想到对整个数组进行排序然后直接取第 k 个元素,但标准的排序算法(如快速排序、归并排序等)的平均时间复杂度是 O(n log n),不满足题目要求的 O(n)。
    • 尝试了快排,但是会超时。
    • 也可以选择快速选择算法,进行对问题的解决。
  2. 构建小堆

    •  首先,从最后一个非叶子节点((数组长度-2)/2  )开始调整(使用 Adjust Down),以确保每个父节点的值都大于其子节点的值。
      • 这个过程称为堆化(Heapify),它将数组转换为一个最大堆。
  3. 提取第 k 个最大元素

    • 由于最大堆的根节点是数组中的最大值,我们可以通过交换根节点与最后一个元素,并减小堆的大小(即不考虑最后一个元素),然后重新调整新的根节点以保持堆的性质。
    • 重复这个过程 k-1 次后,根节点就会是第 k 个最大的元素。

4、代码

class Solution {
public:
	

	//向下调整
	//降序版
	void AdjustDown(vector<int>& nums, int n, int parent)
	{
		//子节点必须在不越界。 child < nums.size()
		int child = parent * 2 + 1;

		while (child < n)
		{
			// 确认child指向小的那个孩子
			if (child + 1 < n && nums[child + 1] < nums[child])
			{
				++child;
			}

			if (nums[parent] > nums[child])
			{
				swap(nums[parent], nums[child]);
				parent = child;
				child = parent * 2 + 1;
			}
			else
				break;
		}
	}

	//降序建小堆
	void HeapSort(vector<int>& nums) {

		//从叶子结点建堆
		for (int i = (nums.size() - 1 - 1) / 2; i >= 0; i--)
		{
			AdjustDown(nums, nums.size(), i);
		}

		int end = nums.size() - 1;
		while (end > 0)
		{
			swap(nums[0], nums[end]);
			AdjustDown(nums, end, 0);
			--end;
		}
	}

	int findKthLargest(vector<int>& nums, int k) {
		HeapSort(nums);
		return nums[k-1];
	}
};

💗感谢阅读!💗


http://www.niftyadmin.cn/n/5680665.html

相关文章

【hot100-java】【划分字母区间】

R9-贪心算法篇 印象题&#xff1a; 我记得&#xff0c;先用字典记录每个字母出现的下标&#xff0c;取出首个字母的下标j,然后我们for循环遍历一次&#xff0c;如果该下标大于 j&#xff0c;就要变化新的首字母&#xff0c;如果相等就说明一个字符串完成&#xff0c;如果小于就…

鸿蒙-app进入最近任务列表触发的监听

如果在UIAbility中&#xff0c;参考第一个链接&#xff0c;在页面中参考如下&#xff1a;State windowStage: window.WindowStage (getContext(this) as common.UIAbilityContext).windowStagetry {this.windowStage.on(windowStageEvent, (data) > {// 前台应用进入最近任…

Python PyQt5 在frame中生成多个QLabel控件和彻底销毁QLabel控件

文章目录 步骤 1: 创建主窗口和布局步骤 2: 添加QLabel到QFrame步骤 3: 销毁QLabel示例代码 在PyQt5中&#xff0c;在QFrame或任何其他容器控件中生成多个QLabel控件并通过一个标志位或方法来彻底销毁这些QLabel控件是相对直接的操作。以下是一个简单的示例&#xff0c;展示了如…

51单片机系列-串口(UART)通信技术

&#x1f308;个人主页&#xff1a; 羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 并行通信和串行通信 并行方式 并行方式&#xff1a;数据的各位用多条数据线同时发送或者同时接收 并行通信特点&#xff1a;传送速度快&#xff0c;但因需要多根传输线&#xf…

【linux】不小心禁用了 nvidia 显卡 PCIe 总线扫描怎么办

问题分析: 系统启动时没有自动加载NVIDIA驱动模块。系统启动时没有自动扫描PCI总线来检测GPU设备。需要手动执行命令来重新扫描PCI总线并加载NVIDIA驱动。 检查内核参数和udev规则: 查看内核启动参数,确保没有影响PCI扫描或GPU检测的参数。检查是否存在NVIDIA相关的udev规则。…

DC00020基于springboot新闻网站系统java web项目MySQL新闻管理系统

1、项目功能演示 DC00020基于springboot新闻网站系统java web项目MySQL 2、项目功能描述 基于springbootvue新闻网站包括用户和系统管理员两个角色。 2.1 用户功能 1、用户登录、用户注册 2、新闻信息&#xff1a;点赞、点踩、收藏、查看 3、用户分享&#xff1a;点赞、点踩…

IP和功能變數名稱的基礎知識-okeyproxy

什麼是IP地址&#xff1f; IP地址是分配給每一個連接到互聯網的設備的唯一識別字。IP地址就像是互聯網中的“門牌號”&#xff0c;它使得數據包能夠在網路中找到正確的目的地。 IP地址有兩種主要類型&#xff1a;IPv4和IPv6。 IPv4&#xff1a;IPv4地址由四個十進位數&#…

【hot100-java】【柱状图中最大的矩形】

R9-栈篇 面积最大矩形的高度一定是 heights 中的元素 简单解释&#xff0c;就是说&#xff0c;最大高度必然是heights中的一个元素&#xff0c;我们假设是h&#xff0c;然后我们基于h&#xff0c;左右拓展&#xff0c;尽量拓展到h越来越高&#xff08;符合单调栈&#xff09;&a…