【算法训练-数组 三】数组中的第K个最大元素(TOPK问题|寻找第K大)

news2024/11/29 18:46:33

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【寻找第K大】,使用【数组】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为:目标公司+最近一年+出现频率排序,由高到低的去牛客TOP101去找,只有两个地方都出现过才做这道题(CodeTop本身汇聚了LeetCode的来源),确保刷的题都是高频要面试考的题。
在这里插入图片描述

名曲目标题后,附上题目链接,后期可以依据解题思路反复快速练习,题目按照题干的基本数据结构分类,且每个分类的第一篇必定是对基础数据结构的介绍

数组中的第K个最大元素【MID】

一道中等难度使用快排可以解决的题

题干

在这里插入图片描述

输入:
[1,3,5,2,2],5,3

返回值:
2
输入:
[10,10,9,9,8,7,5,6,4,3,4,2],12,3

返回值:
9

说明:
去重后的第3大是8,但本题要求包含重复的元素,不用去重,所以输出9      

解题思路

使用快速排序的思路来解决,快速排序(Quick Sort)是一种基于分治思想的排序算法,它通过将数组分成较小和较大的两部分,并分别对这两部分进行排序,最终将整个数组排序。快速排序是一种高效的排序算法,通常在平均情况下具有较快的执行速度。

下面是快速排序的基本思想和步骤:

  1. [划分]选择基准元素(Pivot): 从数组中选择一个元素作为基准元素。

  2. [划分]划分(Partition): 将数组分成两部分,使得基准元素左边的元素都小于等于基准元素,右边的元素都大于基准元素。这一步骤通常称为“划分”。

  3. [解决]递归排序: 递归地对基准元素左边和右边的子数组进行排序。也就是说,对小于基准元素的子数组和大于基准元素的子数组分别执行快速排序。

  4. [合并] 合并: 由于子数组都是在原数组中进行排序,所以最终整个数组也就被排序了。

这些步骤使得较大问题被分解成较小的子问题,这些子问题又能通过递归地应用快速排序来解决。在最好情况下,每次划分都能将数组均匀分成两半,这使得算法的时间复杂度为O(n log n)。

然而,需要注意的是,快速排序的性能高度依赖于基准元素的选择。最坏情况下,如果每次划分都使数组分成极不平衡的两部分,算法的时间复杂度可能会退化到O(n^2)。为了应对这种情况,通常可以选择合适的基准元素,如随机选择或者采用三数取中等方法。

总之,快速排序是一种常用且高效的排序算法,尤其适用于大规模数据的排序。

代码实现

给出代码实现基本档案

基本数据结构数组
辅助数据结构
算法快速排序(分治算法)、二分查找
技巧双指针

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param a int整型一维数组
     * @param n int整型
     * @param K int整型
     * @return int整型
     */
    public int findKth (int[] a, int n, int K) {
        return quikSort(a, 0, n - 1, K);
    }

    public int quikSort(int[] a, int start, int end, int K) {
        // 找到基准元素的位置,这个位置是第 pivot+1(因为数组下标从0开始) 大的元素
        int pivot = partion(a, start, end);
        if (K == pivot + 1 ) {
            // 正好命中
            return a[pivot]  ;
        } else if (K < pivot + 1) {
            // K小于基准位置,说明它是更大的数,在基准位置左边搜索
            return quikSort(a, start, pivot - 1, K);
        } else {
            // K大于基准位置,说明它是更小的数,在基准位置右边搜索,
            return quikSort(a, pivot + 1, end, K );
        }

    }

    // 获取一个基准元素,倒排,所以大于基准元素的数在左,小于基准元素的数在右
    private int partion(int[] a, int start, int end) {
        int pivotValue = a[start];
        int i = start, j = end;
        while (i != j) {
            // (a[j]只有大于基准元素才停止,因为大的放基准元素左边
            while (a[j] <= pivotValue && i < j) {
                // 一定要j先走,因为j先走ij就会在j的位置交汇,而基准元素的左边一定要比自己大,所以为了保证后续基准元素交换正确,一定要保证交汇位置元素值大于等于基准元素,所以要优先满足j的条件(即找到大于基准元素的值并停下),如果i先走,在靠近交互点时,i会越过大于基准元素的值与j交汇。
                j--;
            }

            // (a[i]只有小于基准元素才停止,因为大的放基准元素左边
            while (a[i] >= pivotValue && i < j) {
                i++;
            }

            if (i < j) {
                swap(a, i, j);
            }
        }

        // 全部交换完后,基准元素交换
        swap(a, start, j);
        return j;
    }

    // 辅助函数,交换数组元素
    private void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

复杂度分析

快速排序的时间复杂度和空间复杂度如下:

时间复杂度:

  • 平均情况: 在平均情况下,快速排序的时间复杂度为O(n log n),其中n是待排序数组的长度。这是因为每次划分都能将数组大致均匀地分成两部分,导致递归的深度大约为log n,而每次划分的过程需要O(n)的时间。

  • 最坏情况: 在最坏情况下,如果每次划分都导致一个极不平衡的分割(例如每次选取的基准元素都是当前子数组的最大或最小元素),那么快速排序的时间复杂度可能退化到O(n^2)。这是因为需要执行n次划分,每次划分都需要O(n)的时间。为了避免最坏情况,通常采用随机选择基准元素或者三数取中法来减少极端情况的发生。

  • 最好情况: 快速排序的最好情况时间复杂度为O(n log n),与平均情况相同。这种情况发生在每次划分都能将数组准确地分成相等的两部分时。

空间复杂度:

快速排序的空间复杂度主要取决于递归调用的深度和每次划分所使用的额外空间。

  • 递归调用的深度: 在递归调用中,每次只需要保存一个基准元素的索引和部分数组的边界信息。因此,递归调用的深度为O(log n)

  • 每次划分所使用的额外空间: 每次划分需要O(1)的额外空间来存储基准元素和进行交换。

综合考虑,快速排序的空间复杂度为O(log n)。这是因为虽然递归调用的深度为O(log n),但在每层递归中所需的额外空间是常数级别的。这使得快速排序在空间上比某些其他排序算法(如归并排序)更加节省。

拓展知识:分治算法

分治法是一种解决问题的算法设计范式,它将一个问题分解成多个相似的子问题,然后解决这些子问题,并将它们的解合并以得出原始问题的解。分治法的核心思想是将大问题分解成更小的、相似的子问题,通过解决子问题来解决原始问题。

分治法通常包含三个步骤:分解(Divide)、解决(Conquer)、合并(Combine)。

  1. 分解(Divide): 将原始问题划分为更小、相似的子问题。这一步骤通常是递归地进行的,即将问题逐步分解为更小规模的子问题。

  2. 解决(Conquer): 递归地解决子问题。当子问题足够小,可以直接求解时,就停止分解,转而解决这些子问题。

  3. 合并(Combine): 将子问题的解合并以得出原始问题的解。这是分治法的关键步骤,将各个子问题的解整合起来形成更大问题的解。

分治法通常用于解决一些可以被分解成相似子问题的问题,如排序、搜索、求解最短路径等。典型的分治算法包括归并排序快速排序。以下是一个分治法的示例:

归并排序:

  1. 分解(Divide): 将数组分成两半,分别对这两半进行排序。

  2. 解决(Conquer): 对分解得到的子数组递归地进行排序,直到子数组长度足够小。

  3. 合并(Combine): 将排好序的子数组合并,得到完整的有序数组。

分治法的优点在于它可以将问题分解成独立的子问题,每个子问题的求解都相对简单。这使得算法设计和理解变得更加清晰。然而,分治法有时会在子问题的合并阶段引入额外的开销,因此在设计分治算法时需要权衡分解和合并的成本。

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

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

相关文章

第 3 章 栈和队列(顺序栈,算法 3.3)

1. 背景说明&#xff1a; 若迷宫 maze 中存在从入口 start 到出口 end 的通道&#xff0c;则求得一条存放在栈中(从栈底到栈顶)&#xff0c;并返回 TRUE&#xff1b;否则返回 FALSE&#xff0c;注意&#xff0c;该解并非最优解&#xff0c; 最优解需要求得最短路径且可能并非…

基于Googlenet深度学习网络的人脸身份识别matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ..................................................................... % 定义修改的范围 …

IP子网的划分

文章目录 一、子网掩码1. 产生背景2. 定义3. 分类 二、VLSM算法1. 得出下列参数2. 计算划分结果3. 举例子计算 三、常见子网划分对应关系四、练习IP编址题目需求解题1. 192.168.1.100/282. 172.16.0.58/263. 25.83.149.222/254. 100.100.243.18/205. 10.100.100.100/10 首先可以…

Python Qt学习(一)一个简单的JSON数据预览界面

先贴上代码&#xff1a; # -*- coding: utf-8 -*-# Form implementation generated from reading ui file json_converter.ui # # Created by: PyQt5 UI code generator 5.15.9 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. …

Python飞机大战小游戏

游戏规则&#xff1a;键盘上下左右键控制飞机移动 游戏展示图片&#xff1a; 源码&#xff1a; 第一个py命名为&#xff1a;plane_main.py import pygamefrom plane_sprites import *class PlaneGame(object):# """飞机大战主游戏"""def __in…

ExpressLRS开源之基本调试数据含义

ExpressLRS开源之基本调试数据含义 1. 源由2. 代码2.1 debugRcvrLinkstats2.2 debugRcvrSignalStats 3. 含义解释3.1 ID(packetCounter),Antenna,RSSI(dBm),LQ,SNR,PWR,FHSS,TimingOffset3.2 IRQ_CNT,RSSI_AVE,SNR_AVE,SNV_MAX,TELEM_CNT,FAIL_CNT 4. 总结5. 参考资料 1. 源由 …

详解 ElasticSearch Kibana 配置部署

默认安装部署所在机器允许外网 SSH工具 Putty 链接&#xff1a;https://pan.baidu.com/s/1b6gumtsjL_L64rEsOdhd4A 提取码&#xff1a;lxs9 Winscp 链接&#xff1a;https://pan.baidu.com/s/1tD8_2knvv0EJ5OYvXP6VTg 提取码&#xff1a;lxs9 WinSCP安装直接下一步到完成…

UE 5 GAS 在项目中通过数据初始化

近期&#xff0c;在制作多角色&#xff0c;考虑到角色和角色之间有很多共用的内容&#xff0c;正常项目中的实现的话&#xff0c;会通过数据的方式去实现角色初始化&#xff0c;接下来介绍一下&#xff0c;我的实现方式。 以上是我设置的相应的数据&#xff0c;上面最简单的名…

设计模式行为模式-命令模式

文章目录 前言定义结构工作原理优点适用场景消息队列模式Demo实现分写业务总结 前言 定义 命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;用于将请求封装为对象&#xff0c;从而使你可以使用不同的请求、队列或者日志请求来参数化其他对象…

服务器端污染属性反射提升权限

污染属性反射检测服务器端原型污染 通过服务器端原型污染提升权限 Lab: Privilege escalation via server-side prototype pollution 必要知识点 开发人员很容易陷入的一个陷阱是忘记或忽略 JavaScript 循环迭代对象的所有可枚举属性这一事实&#xff0c;包括它通过原型链继…

医学案例|线性回归

一、案例介绍 某医师预研究糖尿病患者的总胆固醇和甘油三酯对空腹血糖的影响&#xff0c;某研究者调查40名糖尿病患者的总胆固醇、甘油三酯和空腹血糖的测量值如下&#xff0c;试根据上述研究问题作统计分析。 二、问题分析 本案例想要研究一些变量&#xff08;总胆固醇和甘油…

PocketMiner:基于深度学习发现蛋白的隐式口袋

文章目录 1. 文章简介2. 前言3. 方法3.1 模型框架 4. 结果4.1 已知隐式口袋在分子动力学模拟分析迅速打开4.2 图神经网络模型能够准确预测模拟中口袋的动态变化4.3 隐式口袋数据集数据集揭示了新的隐式口袋形成的模式4.4 PocketMiner能够从无配体的蛋白结构中精准预测预测口袋4…

2007-2022年上市公司污染排放数据/2007-2022年上市公司污染排放水平、污染排放量数据

2007-2022年上市公司污染排放数据/2007-2022年上市公司污染排放水平、污染排放量数据 1、时间&#xff1a;2007-2022年 2、指标&#xff1a;证券代码、year、化学需氧量、氨氮排放量、总氮、总磷、水体综合污染当量对数、二氧化硫、氮氧化物、烟尘、空气综合污染当量对数、总…

小游戏分发平台如何以技术拓流?

2023年&#xff0c;小游戏的发展将受到多方面的影响&#xff0c;例如新技术的引入、参与小游戏的新玩家以及游戏市场的激烈竞争等。首先&#xff0c;新技术如虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;和机器人技术都可以带来新颖的游戏体验。其…

滑动窗口实例1(长度最小的子数组)

题目&#xff1a; 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 示例 1&#xff1a; …

VC++使用Microsoft Speech SDK进行文字TTS朗读

Microsoft Speech SDK下载地址 https://www.microsoft.com/en-us/download/details.aspx?id=10121 需要msttss22L.exe、SpeechSDK51.exe、SpeechSDK51LangPack.exe三个,下载后全部安装 使用VS2005建立一个win32控制台项目 朗读"hello word"、中文“你好”的程序 …

百科有不需要的信息怎么删除?

百科词条的权威性众所周知&#xff0c;所以百度百科的内容审核也非常严格&#xff0c;百科营销成为目前网络营销工作中一个难点&#xff0c;很多企业无法得到自己完全满意的百度百科词条 &#xff0c;这其实也是合理的。小马识途营销顾问分析&#xff0c;百科词条内容是提供给广…

10、【WebGIS实战】图层篇——通用服务图层加载全流程(适用于全部图层)

大家好,我是X北辰北。本文是「WebGIS实战」系列,关注这个标签,阅读所有文章,成为WebGIS开发高手。 图层可以理解为添加到地图上面的数据,比如我们要在地图上展示成都市所有大型公园的位置,那么当前地图中除了初始化地图时添加的底图之外,在底图的上面我们还叠加了一份关…

HuggingFace中的 Files and versions 如何优雅下载到本地?(Python requests,tqdm)

前言 在使用huggingface把玩各种大模型时&#xff0c;如果选择从远程加载模型&#xff0c;这个过程可能因为网络问题而非常耗时甚至直接失败&#xff0c;所以把模型、分词器等相关文件下载到本地&#xff0c;再直接从本地加载就成了不可回避的流程。 在进入具体版本的模型后&…

新版Mongodb(6.0以上)找不到mongo.exe

安装目录下/bin目录中&#xff0c;没有mongo.exe文件&#xff0c;只有mongod和mongos&#xff0c;以及一个powershell命令脚本。 原因在于&#xff0c;mongodb6.0以后做出了重大改变&#xff0c;mongodb已经不再默认为你安装shell工具&#xff0c;因此需要安装一个额外的shell…