4.<tag-排序和TopK问题的三种典型解法>补充: 面试题 17.14. 最小K个数 + lt.215-数组中的第K个最大元素 dbc

news/2024/5/19 16:10:37/文章来源:https://blog.csdn.net/nmsLLCSDN/article/details/127225855

面试题 17.14. 最小K个数

[案例需求]

在这里插入图片描述

TopK问题很普遍, 解题套路也很简单, 无非就是排序, 运用最基础的排序(如Array.sort(nums))复杂度为nlogn, 或者使用堆, 复杂度为nlogk,

或者在快排的基础上进行减治
详细参见此文: 点我

[思路分析一, 直接排序]

对原数组从小到大排序后取出前K个数即可;

[代码实现]

class Solution {public int[] smallestK(int[] arr, int k) {int[] vec = new int[k];Arrays.sort(arr);for (int i = 0; i < k; ++i) {vec[i] = arr[i];}return vec;//或者直接拷贝也是可以的;//return Arrays.copyOfRange(nums, 0, k);}
}

在这里插入图片描述

[思路分析二, 使用堆]

我们使用一个大根堆实时维护数组的前k小值,
首先将前k个数插入到大根堆中, 随后从第k+1个数开始遍历,
如果当前遍历到的数比大根堆的堆顶的数要小, 就把堆顶的数弹出, 再插入到当前遍历到的数,
最后将大根堆的数存入到数组返回即可.

注意, 之所以使用大顶堆来维护最小的K个数是因为, 每次都是将新元素和堆顶(也就是这k个数中最大的数进行比较), 每次替换掉的都是这K个数中最大的数, 慢慢的等遍历完之后, 堆中K个数的最大, 较大, 次大…都被替换为了较小的数, 进而能够获得最小的K个数。

  • (简单来说就是, 堆中K个数, 每次我清洗最大的数, 把他换成较小的数, 遍历完了整个序列后, 就获得了最小的K个数); 要想每次都能直接获得最大的数, 那肯定使用的是大顶堆咯;

[代码实现]

由于Java中优先队列是小根堆实现的, 所以我们要重新自定义比较器, 把数组排成单调递减的数;

class Solution {public int[] smallestK(int[] arr, int k) {int[] ans = new int[k];if(k == 0)return ans;//优先队列是小根堆实现的, 正好能够用来存储K的数, 比较合适替换后len - k 个数//单调递减, 小根堆//单调递增, 大根堆;PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>(){public int compare(Integer num1, Integer num2){return num2 - num1;}});//往堆中放入k个数for(int i = 0; i < k; i++){queue.offer(arr[i]);}//System.out.println(queue.peek());//比较len - k 个数和堆顶元素(queue.peek())for(int i = k; i < arr.length; i++){if(queue.peek() > arr[i]){queue.poll();queue.offer(arr[i]);}}for(int i = 0; i < k; i++){ans[i] = queue.poll();}return ans;//4. 随机选择, n}
}

在这里插入图片描述

在这里插入图片描述

[思路分析三, 随机选择(利用了快排思想, 但是减治)]

  • 我们可以借鉴快排思想, 再快排中, 划分函数每次执行完之后会得到一个划分值partition, 这个值把数组分为了两个部分, 小于等于基准值pivot的元素都会被放到数组的左边, 大于的都会被放到数组的右边, 然后返回分界值的下标, 与快排不同的在于, 这里我们只处理划分的一边, 简单来说我们这种方法属于减治算法而不是快排的分治算法;

具体说明见前文(方法三, 随机选择) : 点我

我们定义函数 randomSelect(arr, left, right, k) 表示划分数组arr的[left, right]部分, 使得前k小 的数在数组的左侧, 在函数里我们调用快排的划分函数getPartition(), 假设划分函数返回的下标为partition(表示的是分界值(或基准值) 最终在数组中的位置), 即pivot是数组中第parition - left + 1 小的数, 那么会有这么三种情况:

  1. 如果 partiton - left + 1 == k , 表示pivot就是第k小的数, 直接返回即可;
  2. 如果 partition - left + 1 < k , 表示第k小的数在pivot的右侧, 因此递归调用randomSelect(arr, partition + 1, right, k - (partition - left + 1));
  3. 如果 partition - left + 1 > k , 表示第k小的数在pivot的左侧, 递归调用randomSelect(arr, left, partition - 1, k);

函数递归入口为 randomized_selected(arr, 0, arr.length - 1, k)。在函数返回后,将前 k 个数放入答案数组返回即可。
在这里插入图片描述

[代码实现]

class Solution {public int[] smallestK(int[] arr, int k) {randomSelect(arr, 0, arr.length - 1, k);return Arrays.copyOfRange(arr, 0, k);}/**1. 根据划分函数确定基准值的位置partition;2. 如果partition - left + 1 == k, 那么返回left ==> partiton即可;3. 如果 partition - left + 1 > k, 问题缩小为左边界 left -> partition - 1;4. 如果partition - left + 1 < k, 前partition - left + 1 已经确定还需要去有边界确定 k - (partition - left + 1)*/public void randomSelect(int[] arr, int left, int right, int k){if(left < right){int partition = getRandomPartition(arr, left, right);int num = partition - left + 1;if(num == k){return;}else if(num > k){randomSelect(arr, left, partition - 1, k);}else{randomSelect(arr, partition + 1, right, k - (num));}}}public int getRandomPartition(int[] arr, int left, int right){int randomleft = new Random().nextInt(right - left + 1) + left;swap(arr, left, randomleft);return getPartition(arr, left, right);}public int getPartition(int[] arr, int left, int right){int pivot = arr[left];int tempLeft = left;while(left < right){while(left < right && arr[right] >= pivot)--right;while(left < right && arr[left] <= pivot)++left;swap(arr, left, right);}swap(arr, left, tempLeft);return left;}public void swap(int[] nums, int left, int right){int temp = nums[left];nums[left] = nums[right];nums[right] = temp;}
}

在这里插入图片描述

以上解法跟lt.215 基本相同, 仅在细微处做一些改变而已;

拓展: 自实现堆解决TopK问题;

在这里插入图片描述

可先参考前文: 堆排序的Java实现: 点我

这里先偷个懒把官解的代码贴上(写的是真烂, 无力吐槽), 以后尽快补上;

class Solution {public int findKthLargest(int[] nums, int k) {int heapSize = nums.length;buildMaxHeap(nums, heapSize);for (int i = nums.length - 1; i >= nums.length - k + 1; --i) {swap(nums, 0, i);--heapSize;maxHeapify(nums, 0, heapSize);}return nums[0];}public void buildMaxHeap(int[] a, int heapSize) {for (int i = heapSize / 2; i >= 0; --i) {maxHeapify(a, i, heapSize);} }public void maxHeapify(int[] a, int i, int heapSize) {int l = i * 2 + 1, r = i * 2 + 2, largest = i;if (l < heapSize && a[l] > a[largest]) {largest = l;} if (r < heapSize && a[r] > a[largest]) {largest = r;}if (largest != i) {swap(a, i, largest);maxHeapify(a, largest, heapSize);}}public void swap(int[] a, int i, int j) {int temp = a[i];a[i] = a[j];a[j] = temp;}
}作者:LeetCode-Solution
链接:https://leetcode.cn/problems/kth-largest-element-in-an-array/solution/shu-zu-zhong-de-di-kge-zui-da-yuan-su-by-leetcode-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

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

相关文章

毕业设计 深度学习 机器视觉 车位识别车道线检测 - python opencv

0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过…

Airflow学习笔记

CSDN话题挑战赛第2期 参赛话题&#xff1a;学习笔记 项目中解决的问题 使用airflow调度hive脚本跑批任务 视频教程上整理知识点 学习视频&#xff1a;https://www.bilibili.com/video/BV1V7411K7Gy?p40&vd_sourceb002288652bae647c598ddf77f79a7b8 Airflow基本概念 Airfl…

【VUE2开发20221004】-day1.0

目录测试案例1&#xff1a;Vue常见指令&#xff1a;1、插值表达式2、v-bind指令v-bind指令注意事项简写v-bindv-bind属于单向绑定&#xff08;JS修改->HTML修改&#xff09;3、v-model指令v-model常用标签4、v-for指令5、v-on事件前端开发教程链接 vuejs官方教程 框架&…

刷题笔记-栈帧

例题1 阅读如下C代码片段&#xff08;其中Y表示代码指令地址&#xff09;&#xff1a; void overflow(char* pShellcode, int iLen) { Y1&#xff1a;char buffer[8]; Y2: memcpy(buffer, pShellcode, dwLen); Y3: „„ } Y4: int main() { Y5: „„ Y6: overflow("123…

多处理机的基本概念

本文内容是作者在进行计算机组成原理复习的时候&#xff0c;用王道的视频做笔记或者保存图的内容。后续如果看了其他书或者有其他理解会进行增加内容。 SISD&#xff08;单指令流数据流&#xff09; 特性&#xff1a;各指令序列只能并发、不能并行&#xff0c;每条指令处理一…

Prophet算法

Prophet简介 Prophet是FaceBook公司在2017年开源的一款时间序列建模工具。Prophet的方法是将时间序列看成是关于t的一个函数&#xff0c;用你和函数曲线的方法进行预测&#xff0c;所以这和传统的时间序列模型有本质上的区别&#xff0c;他更倾向于机器学习的建模方式。 Prop…

PO/PI

典型集成场景 PI总体架构

浅学设计模式(二)

目录&#xff1a; &#xff08;1&#xff09;工厂模式 简单工厂&#xff1a; 工厂方法模式&#xff1a; &#xff08;2&#xff09;抽象工厂模式 &#xff08;1&#xff09;工厂模式 简单工厂&#xff1a; 原来的方式使用new&#xff1a; 需要关心细节&#xff0c;如何创建对…

独家分享 圆梦阿里之后,我得到了这份SpringCloud Alibaba源码文档

Spring Cloud Alibaba为分布式应用开发提供了一站式解决方案。它包含开发分布式应用程序所需的所有组件&#xff0c;可以轻松地使用Spring Cloud开发应用程序。 使用Spring Cloud Alibaba&#xff0c;只需添加一些注解和少量配置&#xff0c;即可将Spring Cloud应用连接到Alib…

Spring 4 IOC 相关内容 4.2 bean 实例化 3 实例工厂实例化

Spring 【黑马程序员2022新版SSM框架教程_SpringSpringMVCMaven高级SpringBootMyBatisPlus企业实用开发技术】 4 IOC 相关内容 文章目录Spring4 IOC 相关内容4.2 bean 实例化4.2.5 实例工厂与FactoryBean4.2.6 bean 实例化小结4.2 bean 实例化 4.2.5 实例工厂与FactoryBean …

Python学习笔记(四)——字符串与文本处理2

目录 字符串函数大合集 两端删除函数strip() 删除空白字符 删除两端指定字符 右端删除函数rstrip() 左端删除函数 字符串对齐 返回指定宽度字符串center() 原字符串居中对齐、左对齐、右对齐 字符串开始或结束符判定startswith()、endswith() 内置函数eval()&#x…

web期末作业设计网页 html+css+js制作非物质文化遗产坝漆国漆 2页

&#x1f329;️ 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f482; 作者主页: 【进入主页—&#x1f680;获取更多源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;HTML5网页期末作业 (1000套…

鉴源论坛丨民用飞机机载软件是如何表明适航符合性的

作者 | 蔡喁 上海控安可信软件创新研究院副院长 版块 | 鉴源论坛 观擎 01 机载软件的基本特征 机载计算机在现代飞机各组成部分中占有举足轻重的位置&#xff0c;是现代航空电子系统的基础和核心&#xff0c;其研制、生产和应用水平已成为衡量飞机先进性的重要标志。机载计…

【面试题】Java基础 2

若你困于无风之地&#xff0c;我将为你奏响高空之歌 文章目录一、int 和 Integer 对象1. int 和 Integer 对象的区别2. 变量比较问题&#xff1a;二、反射1. 反射机制定义2. 反射的使用步骤3. 一个小栗子4. 反射的应用一、int 和 Integer 对象 1. int 和 Integer 对象的区别 …

css 特效实现方法

背景渐隐 通过 before 线性渐变遮盖掉一部分图片 视察滚动实现方式&#xff1a; 监听浏览器滚动事件改变各个层的top值 环形进度条 svg circlestroke-dasharray 环绕边框动画 四个单向运动的动画父框overflow: hidden;设置延迟可表现循环 一些旋转曲线的图形 inset背景扩…

一维无界的自由波动问题-达朗贝尔行波解

回顾 第一个例子 表示热能的扩散&#xff0c;在空间有不同的取值&#xff0c;随空间和时间而变化&#xff0c;左端是跟一个恒温为0的热源接触&#xff0c;我们表示为&#xff0c;这个叫恒温条件。右端我们跟一个绝热的材料接触&#xff0c;傅里叶发现了热传导规律,K叫做热传导…

Java学习笔记 --- 面向对象之多态

一、基本介绍 方法或对象具有多种形态&#xff0c;是面向对象的三大特征&#xff0c;多态是建立在封装和继承之上的 二、多态的具体体现 1、方法的多态&#xff1a; 重写和重载就体现多态 案例演示&#xff1a; package com.javase.poly_;public class PloyMethod {publi…

最新案例 | 昇思MindSpore携手信大网御推出中原AI反诈骗创新解决方案,为全民反诈筑牢防火墙

近日&#xff0c;河南信大网御科技有限公司的中原人工智能反诈骗创新解决方案与华为Atlas 800训练服务器和全场景AI框架昇思MindSpore完成兼容性测试。该方案基于昇腾AI基础软硬件平台&#xff0c;能够在短时间内对涉诈网址/APP进行识别&#xff0c;识别准确率高达99%。 据2021…

嵌入式开发为什么用C语言

有了解过嵌入式开发的人都会想要多去了解一些嵌入式方面的信息&#xff0c;那么既然是嵌入式开发肯定是要你会代码的&#xff0c;至于这些可能你还不是很了解&#xff0c;下面可以一起来了解下嵌入式开发为什么用C语言吧。 点击获取1V1嵌入式学习规划&#xff0c;现在还送100G精…

牛客网刷题-两个队列实现栈

✅作者简介&#xff1a;嵌入式入坑者&#xff0c;与大家一起加油&#xff0c;希望文章能够帮助各位&#xff01;&#xff01;&#xff01;&#xff01; &#x1f4c3;个人主页&#xff1a;rivencode的个人主页 &#x1f525;系列专栏&#xff1a;《牛客网刷题》 &#x1f4ac;推…