大厂面试:找出数组中第k大的数的最佳算法

news2024/11/28 4:43:11

一.前置条件
假如数组为a,大小为n,要找到数组a中第k大的数。

二.解决方案
1.使用任意一种排序算法(例如快速排序)将数组a进行从大到小的排序,则第n-k个数即为答案。


2.构造一个长度为k的数组,将前k个数复制过来并降序排序。然后依次将 k+1 到 n 位的数分别插入 k 长度的数组中并保持数组长度为k且降序排列。最终长度为k的数组的最后一个元素即是答案。


3.将数组的所有元素构造一个大顶堆,然后删除堆顶元素k次并重新构成大顶堆,则第k次操作后的堆顶元素即为答案。
4.用快速排序的思想不把数组元素全排序的优化算法。
1)先看一下快速排序(降序排序)的算法。

/**
快速排序主函数
a:要排序的数组
left:排序数组左边界索引
right:排序数组右边界索引
*/
public void quickSort(int a[], int left, int right) {
    if (left < right) {
        //算出基准元素索引值index
        int index = partition(a, left, right);
        //对低于index索引的数组递归排序
        quickSort(a, left, index - 1);
        //对高于index索引的数组递归排序
        quickSort(a, index + 1, right);
    }

}

//算出基准元素索引值,此索引值左侧值都大于基准元素值,此索引值右侧值都小于基准元素值
public int partition(int[] num, int left, int right) {
    if (num == null || num.length <= 0 || left < 0 || right >= num.length) {
        return 0;
    }
    //获取数组基准元素的下标
    int prio = num[left + (right - left) / 2]; 
    //从两端交替向中间扫描    
    while (left <= right) {                 
        while (num[left] > prio)
            left++;
        while (num[right] < prio)
            right--;
        if (left <= right) {
            //将不符合条件的元素值交换位置并继续扫描
            swap(num, left, right);        
            left++;
            right--;
        }
    }
    return left;
}

//交换元素
public void swap(int[] num, int left, int right) {
    int temp = num[left];
    num[left] = num[right];
    num[right] = temp;
}

2)我们选择数组区间 a[0…n-1]的中间位置的一个元素 a[n/2]作为 pivot,对数组 a[0…n-1]进行分区,这样数组就分成了三部分,a[0…p-1]、a[p]、a[p+1…n-1]。
如果 p+1=k,那 a[p]就是要求解的答案;如果 k>p+1, 说明第 k 大元素出现在 a[p+1…n-1]区间,我们再按照上面的思路递归的在 a[p+1…n-1]这个区间内查找。同理,如果 k<p+1,那就在 a[0…p-1]区间内递归查找。

3)所以改进后的代码如下:

public int quickSortKthLargest(int a[], int left, int right, int k) {
    if (left < right) {
        //算出基准元素索引值index
        int index = partition(a, left, right);
        //索引对应的值就是第k大的数
        if(index+1==k){
            return a[index];
        }
        //在索引左边继续查找
        else if(index+1>k){
            return quickSortKthLargest(a, left, index-1, k);
        } 
        //在索引右边继续查找
        else{
            return quickSortKthLargest(a, index+1, right, k);
        }
        
    }else{
        return -1;
    }

}


5.在Python中,我们可以使用内置的heapq库来查找数组的第k大元素。heapq库实现了一个堆数据结构,我们可以利用堆的性质来找到数组的第k大元素。
代码如下:

# 返回第k大元素
def get_kth_largest(a, k): 
    # heapq.nlargest(k, a)会返回数组a中最大的k个元素,
    # 然后我们通过[-1]来取得这k个元素中的最后一个,也就是第k大的元素。
    return heapq.nlargest(k, a)[-1]


6.使用最小堆来查找第k大的元素。
首先构建一个空的最小堆。遍历数组a,如果堆的大小小于k,我们就把当前元素加入堆中。如果堆的大小已经达到了k,我们就比较当前元素和堆顶元素(也就是堆中的最小元素),如果当前元素大于堆顶元素,我们就把堆顶元素替换为当前元素,再重新调整最小堆结构。这样,当遍历完整个数组后,堆顶元素就是数组的第k大元素(即是大小为k的最小堆(保存了数组中的最大的k个数)的最小元素)。
代码如下:

def get_kth_largest(a, k):  
    heap = []  
    for num in a:  
        # 若最小堆大小小于k,则将元素插入最小堆
        if len(heap) < k:  
            heapq.heappush(heap, num)  
        else:  
            # 若元素大于最小堆堆顶元素,则插入最小堆并重新排列
            if num > heap[0]:  
                heapq.heapreplace(heap, num)  
    # 堆顶元素即为数组的第k大元素
    return heap[0]  


致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享。

若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢。您的支持是我们为您提供帮助的最大动力。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

笔记:[dv-admin开发系列]--2.0版本环境搭建

目录 来源新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公…

基于51单片机的病床呼叫系统设计与实现Proteus仿真

地址&#xff1a;https://pan.baidu.com/s/1bybQ0wc-FNtkemkFvGotsA 提取码&#xff1a;1234 仿真图&#xff1a; 利用矩阵键盘、蜂鸣器和数码管搭建一个小型病床呼叫系统。用16个按键模拟16个病床的呼叫按钮&#xff0c;当有按键按下时&#xff0c;护士站处由蜂鸣器发出报警声…

广告投放分析

项目背景 Facebook被众多企业作为首选的广告平台之一&#xff0c;特别是在投放原生广告方面。这个平台允许根据如性别、年龄、地理位置和兴趣等多重标准来细化目标用户群。广告主能够制作专门的Facebook广告&#xff0c;并设定一个特定的“受众群体”&#xff0c;便于他们向某些…

django 4.2 自定义signal的使用方法

环境&#xff1a;win11 python3.9.2 django 4.2.11 背景&#xff1a;执行异步数据存储&#xff0c;想要使用该方法实现&#xff08;失败了&#xff09; 时间&#xff1a;20240410 说明&#xff1a;记录一下&#xff0c;避免忘记 1、创建django项目&#xff0c;并实现首页 …

vue点击上传图片并实现图片预览功能,并实现多张图片放到一个数组中进行后端请求(使用原生input)

一、将 File 对象转成 BASE64 字符串 &#xff08;FileReader&#xff09; <template><div><!-- 用来显示封面的图片 --><!-- <img src"/assets/images/cover.jpg" alt"" class"cover-img" ref"imgRef" />…

蓝桥杯嵌入式2023年第十四届省赛主观题解析

1 题目 2 代码 /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "adc.h" #include "rtc.h" #include "tim.h" #include "gpio.h"/* Private includes --…

Leetcode:27.移除元素

题目要求 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出…

C语言指针—野指针、指针运算、指针与数组

野指针 指针未初始化 int main(){int *p;//没有初始化&#xff0c;就意味着没有明确的方向//一个局部变量不初始化&#xff0c;放的是随机值:0xCCCCCCCC//请注意&#xff0c;这个地址并不是我们定义的&#xff0c;是一个非法的地址*p 10;//非法访问内存了&#xff0c;这里的…

Unity面经(自整)——移动开发与Shader

Unity与Android混合开发 为什么使用Flutter构建 Flutter 是 Google 的开源工具包&#xff0c;用于从单个代码库为移动、Web、桌面和嵌入式设备构建应用程序&#xff08;一套代码跨平台构建app是它最大的优点&#xff09;&#xff0c;并且可以构建高性能、稳定和丰富UI的应用程…

Spring MVC体系结构和处理请求控制器(一)

一、MVC模式 MVC模式是指Model-View-Controller&#xff08;模型-视图-控制器&#xff09;模式&#xff0c;是开发Web应用程序时常用的一种代码分层模式MVC模式是软件工程中的一种架构模式&#xff0c;会强制行的把系统的输入、处理和输出分开&#xff0c;是系统从功能上形成M…

评论发布完整篇(react版)

此篇文章阐述评论的最新、最热之间的tab标签切换&#xff08;包括当前所在tab标签的高亮显示问题&#xff09;&#xff1b;当前评论的删除&#xff1b;除此之外还延伸了用户的评论实时发布功能。其中最新tab标签所展示的内容是根据当前评论点赞数来进行排序&#xff0c;点赞数量…

数字社会下的智慧公厕:构筑智慧城市的重要组成部分

智慧城市已经成为现代城市发展的趋势&#xff0c;而其中的数字化转型更是推动未来社会治理体系和治理能力现代化的必然要求。在智慧城市建设中&#xff0c;智慧公厕作为一种新形态的信息化公共厕所&#xff0c;扮演着重要角色。本文智慧公厕源头实力厂家广州中期科技有限公司&a…

Go gin框架(详细版)

目录 0. 为什么会有Go 1. 环境搭建 2. 单-请求&&返回-样例 3. RESTful API 3.1 首先什么是RESTful API 3.2 Gin框架支持RESTful API的开发 4. 返回前端代码 go.main index.html 5. 添加静态文件 main.go 改动的地方 index.html 改动的地方 style.css 改动…

C语言 | 字符函数和字符串函数

目录&#xff1a; 1. 字符分类函数 2. 字符转换函数 3. strlen的使用和模拟实现 4. strcpy的使用和模拟实现 5. strcat的使用和模拟实现 6. strcmp的使用和模拟实现 7. strncpy函数的使用 8. strncat函数的使用 9. strncmp函数的使用 10. strstr的使用 11. strtok函…

力扣121. 买卖股票的最佳时机

Problem: 121. 买卖股票的最佳时机 文章目录 题目描述思路复杂度Code 题目描述 思路 1.定义一个int数组max大小同prices&#xff1b;定义int变量curMax初始化为0&#xff1b; 2.从后往前遍历数组&#xff0c;若当前元素prices[i] > curMax时&#xff0c;则使将其赋值给curMa…

医院预约系统微信小程序APP前后端

医院预约系统具体功能介绍&#xff1a;展示信息、可以注册和登录&#xff0c; 预约&#xff08;包含各个科室的预约&#xff0c;可以预约每个各个医生&#xff09;&#xff0c;就诊引导包含预约的具体信息&#xff0c;包含就诊时间、就诊科室、就诊医生以及就诊人信息、和支付状…

如何注册midjourney账号

注册Midjourney账号比较简单&#xff0c;准备好上网工具&#xff0c;进入官网 Midjourney访问地址&#xff1a; https://www.midjourney.com/ 目前没有免费使用额度了&#xff0c;会员最低 10 美元/月&#xff0c;一般建议使用30美元/月的订阅方案。了解如何订阅可以查看订阅…

MyBatis源码介绍

文章目录 MyBatis的核心流程介绍SqlSessionFactory的理解MyBatis中的Executor的源码理解Spring中是如何解决MySQL的SqlSession的线程安全问题MyBatis面向Mapper编程工作原理Mybatis动态sql执行原理Mybatis的一级、二级缓存实现原理Mybatis的插件运行原理以及如何编写一个插件my…

019——IIC模块驱动开发(基于EEPROM【AT24C02】和I.MX6uLL)

目录 一、 IIC基础知识 二、Linux中的IIC&#xff08;韦东山老师的学习笔记&#xff09; 1. I2C驱动程序的层次 2. I2C总线-设备-驱动模型 2.1 i2c_driver 2.2 i2c_client 三、 AT24C02 介绍 四、 AT24C02驱动开发 实验 驱动程序 应用程序 一、 IIC基础知识 总线类…

【linux】谈MobaXterm支持的连接方式

目前远程联机服务器主要有文字命令行接口和图形界面接口两种。 一、命令行接口方式 1.1 加密传输-SSH SSH为主&#xff0c;目前大多在网络上的数据封包都是加密的技术&#xff0c;等到传输的封包加密后再传输到网络上&#xff0c;以增加数据在Internet上面传送的安全性 1.2…