当前位置:网站首页>数组中的第K大元素[堆排 + 建堆的实际时间复杂度]
数组中的第K大元素[堆排 + 建堆的实际时间复杂度]
2022-06-28 15:15:00 【REN_林森】
堆排+建堆的时间复杂度
前言
堆排可以不用完全排序,再取第K大元素,但是选择排序也亦如此。
那么谁会运行的更快呐?建堆时,需要调整n/2次,每次最大深度为log2(n),第一直观印象就是建堆T(n) = O(nlgon),其实不然。
堆排取k大元素的时间 = 建堆时间 + 取k个元素的时间 = (O(n) - O(log2n) - 1) + O(klog2n) = O(n);
选择排序取k大元素的时间 = O(kn) = O(n).
因为(O(n) - O(log2n) - 1) + O(klog2n) <O(kn),所以堆排要快些。
证明在第二部分代码前的注释中。
一、数组中的第K大元素

二、建堆复杂度证明
证明:以最多节点的满二叉树为例,树高为h,
设当前层为k,则该层有2^(k - 1)^个节点,每个节点需要调整h - k的深度。
所以,T(n) = 20 * (h - 1) + 21 * (h - 2) +…+2^(h - 2) * 1,显然是一个典型的差比数列,只需错位相减即可。
2T(n) = 21 * (h - 1) + 22 * (h - 2) +…+2^(h - 2)^ * 2 + 2^(h - 1) * 1,
两式差得T(n) = 2h - h - 1,注:h = log2(n),所以T(n) = O(n) - O(log2(n)) - 1 = O(logn)
注:计算复杂度,前提条件就是n足够大,如果n很小,就无复杂度可言,直接O(1)
三、快排/优先队列/堆排
package everyday.medium;
import java.util.PriorityQueue;
// 数组中第k个最大元素。
public class FindKthLargest {
/* target:取数组中第K大元素,把数组排个序,取nums[k - 1]即可,但时间复杂度O(nlogn),不可取。 选择排序,选择第K个,时间复杂度O(kn),即O(n),可行。 堆排,建堆要花O(nlogn),选第k大,花O(klogn),时间复杂度O( ),不可行。 为什么建堆要花O(nlogn)?我们直观的感觉,要调整n/2次(从倒数第二行开始调整),每次调整向下O(logn)(自然而然取了最大的一次)。 所以建堆要花O(nlogn)。但是这是错觉。实际的时间复杂度为Tn = 2^log2(n)^ - log2(n) - 1 =O(n) - O(logn) = O(n)(当n很大时) 证明:以最多节点的满二叉树为例,树高为h, 设当前层为k,则该层有2^(k - 1)^个节点,每个节点需要调整h - k的深度。 所以,T(n) = 2^0^ * (h - 1) + 2^1^ * (h - 2) +...+2^(h - 2) * 1,显然是一个典型的差比数列,只需错位相减即可。 2T(n) = 2^1^ * (h - 1) + 2^2^ * (h - 2) +...+2^(h - 2)^ * 2 + 2^(h - 1) * 1, 两式差得T(n) = 2^h^ - h - 1,注:h = log2(n),所以T(n) = O(n) - O(log2(n)) - 1 = O(logn) 注:计算复杂度,前提条件就是n足够大,如果n很小,就无复杂度可言,直接O(1) */
// 选择排序 -- 虽然是O(n),但时间是Tn = kn,比起堆排,Tn = n - log(n+1) + klogn,还是要慢很多。
public int findKthLargest(int[] nums, int k) {
for (int i = 0; i < k; i++) {
// 选择
int max = nums[i], idx = i;
for (int j = i + 1; j < nums.length; j++) {
if (max < nums[j]) {
max = nums[j];
idx = j;
}
}
// swap
int t = nums[idx];
nums[idx] = nums[i];
nums[i] = t;
}
// 取值
return nums[k - 1];
}
// 堆排,熟练API,优先队列,整个大顶堆。
public int findKthLargest2(int[] nums, int k) {
// 大顶堆
PriorityQueue<Integer> que = new PriorityQueue<>((o1, o2) -> o2 - o1);
// 加入元素
for (int num : nums) que.offer(num);
// 把第1 - (k-1)大的元素取出
for (int i = 0; i < k - 1; i++) que.poll();
// 取第K大
return que.poll();
}
// 堆排,API有太多累赘的地方,直接堆排。
public int findKthLargest3(int[] nums, int k) {
// 建堆,从倒数第二层有孩子的节点开始调整。
for (int i = nums.length - 1 >>> 1; i >= 0; i--) adjustHeap(nums, i, nums.length);
// 排前K个大元素出来。
int i = 0;
do {
// swap
int t = nums[0];
nums[0] = nums[nums.length - 1 - i];
nums[nums.length - 1 - i] = t;
// 调整堆,让堆顶为最大元素。
if (++i >= k) break;
adjustHeap(nums, 0, nums.length - i);
} while (true);
// 取第k个最大元素
return nums[nums.length - k];
}
// 堆排核心:调整堆
private void adjustHeap(int[] nums, int k, int end) {
int ori = nums[k]; // 记住要调整的原始元素。
// 不断向下调整
for (int i = (k << 1) + 1; i < end; i = (i << 1) + 1) {
// 看左孩子还是右孩子大。
if (i + 1 < end && nums[i + 1] > nums[i]) ++i;
// 看是否有必要和孩子交换。
if (ori >= nums[i]) break;
// 向下调整
nums[k] = nums[i];
// 得到原始元素的新位置。
k = i;
}
// 把原始元素放到它最后交换到的空位上。
nums[k] = ori;
}
}
总结
1)堆排建堆的时间复杂度是O(n),不是O(nlogn).
2)优先队列/堆排/选择排序。
参考文献
边栏推荐
- halcon 基础总结(一)裁切图片并旋转图像
- 一种跳板机的实现思路
- C语言学习-19-全排列
- 【黑马早报】腾讯回应大批用户QQ号被盗;薇娅丈夫公司被罚19万;中国恒大被申请清盘;关晓彤奶茶店回应被加盟商起诉...
- Classmate Zhang hasn't learned to be an anchor yet
- Not being a meta universe now is like not buying a house 20 years ago!
- 新零售线下店逆势起飞,通膨乌云下的消费热情
- ROS21讲
- 隆重推出 Qodana:您最爱的 CI 的代码质量平台
- Power battery is divided up like this
猜你喜欢

MIPS assembly language learning -02- logic judgment - foreground input
![[C language] how to generate normal or Gaussian random numbers](/img/31/964e0922e698a3746599b840501cdf.png)
[C language] how to generate normal or Gaussian random numbers

教育行业SaaS应用管理平台解决方案:助力企业实现经营、管理一体化

Jackie Chan and fast brand, who is the Savior of Kwai?
Oracle11g database uses expdp to back up data every week and upload it to the backup server

MIPS assembly language learning-01-sum of two numbers, environment configuration and how to run

MIPS汇编语言学习-01-两数求和以及环境配置、如何运行

How to build a 100000 level QPS large flow and high concurrency coupon system from zero

石油化工行业供应链系统驱动管理模式创新升级,强化企业内部管理

How can the digital intelligent supply chain management platform of the smart Park optimize process management and drive the development of the park to increase speed and quality?
随机推荐
信创操作系统--麒麟Kylin桌面操作系统 (项目十 安全中心)
分布式 CAP 定理的前世今生
ROS知识点——使用VScode搭建ROS开发环境
ROS21讲
ROS知识点——ROS创建工作空间
R语言ggplot2可视化:使用patchwork包(直接使用加号+)将一个ggplot2可视化结果和一个plot函数可视化结果横向组合起来形成最终结果图、将两个可视的组合结果对齐
Cross cluster deployment of helm applications using karmada
The best time to buy and sell stocks
Do not use short circuit logic to write STL sorter multi condition comparison
智慧园区数智化供应链管理平台如何优化流程管理,驱动园区发展提速增质?
How to solve the following problems in the Seata database?
ROS知识点——话题消息的定义与使用
spacy教程(持续更新ing...)
新零售线下店逆势起飞,通膨乌云下的消费热情
MIPS assembly language learning-03-cycle
R language ggplot2 visualization: use the patchwork package (directly use the plus sign +) to horizontally combine a ggplot2 visualization result and a data table to form a final result graph
Gbase Nantah General Motors appears at the 6th World Intelligence Conference
S2b2c system website solution for kitchen and bathroom electrical appliance industry: create s2b2c platform Omni channel commercial system
【黑马早报】腾讯回应大批用户QQ号被盗;薇娅丈夫公司被罚19万;中国恒大被申请清盘;关晓彤奶茶店回应被加盟商起诉...
SAP MTS/ATO/MTO/ETO专题之九:M+M模式前后台操作,策略用50,提前准备原材料和半成品