线性时间选择[C++,附代码]

news/2025/3/11 15:46:55/文章来源:https://www.cnblogs.com/hello-nullptr/p/18572297

0 引言

问题:从无序数组中选择第k小的元素。

1 随机选择法

1.1 算法步骤:

  1. 选择基准元素:随机选择一个元素作为基准。

  2. 分区:对数组进行分区,使得基准元素左边的所有元素都小于它,右边的所有元素都大于它。分区过程完成后,我们得到了基准元素在数组中的位置pivotIndex。

  3. 递归选择:
    如果pivotIndex == k - 1(注意数组索引从0开始),则基准元素就是第k小的元素。
    如果pivotIndex < k - 1,则第k小的元素在右子数组中,递归地在右子数组中寻找第(k - pivotIndex - 1)小的元素。
    如果pivotIndex > k - 1,则第k小的元素在左子数组中,递归地在左子数组中寻找第k小的元素(注意此时k值不变,因为我们在子数组中重新计数)。

1.2 算法图解

image

1.3 算法复杂度

随机选择法通过随机选取基准元素进行划分,平均时间复杂度为O(n),最坏时间复杂度为O(n^2)

1.4 代码实现

点击查看代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;/// <summary>
/// 输出向量
/// </summary>
/// <param name="c">输出流</param>
/// <param name="v">向量</param>
/// <returns>输出流</returns>
ostream& operator<<(ostream& c, vector<int> v)
{cout << "[ ";for (int a : v){cout << a << ' ';}cout << "]\n";return c;
}/// <summary>
/// 分割序列,默认使用a[p]分割,使小于a[p]元素位于左侧,反之位于右侧
/// </summary>
/// <param name="a">序列,对a具有破坏性</param>
/// <param name="p">左下标</param>
/// <param name="r">右下标</param>
/// <returns>分割点下标</returns>
int Partition(vector<int>& a, int p, int r)
{int i = p, j = r;int x = a[p];while (i<j){while (i < j && a[i] < x){++i;}while (i<j && a[j] > x){--j;}swap(a[i], a[j]);}a[j] = x;return j;
}/// <summary>
/// 随机选择
/// </summary>
/// <param name="a">线性序列,对a有破坏性</param>
/// <param name="p">左下标</param>
/// <param name="r">右下标</param>
/// <param name="k">第k小元素</param>
/// <returns>第k小元素值</returns>
int RandomizedSelect(vector<int>& a, int p, int r, int k)
{assert(k <= a.size());int nSplit = Partition(a, p, r);vector<int> vLeft(a.begin(), a.begin() + nSplit);vector<int> vRight(a.begin() + nSplit + 1, a.end());if (vLeft.size() == k - 1){return a[nSplit];}else if (k <= vLeft.size()){return RandomizedSelect(vLeft, 0, vLeft.size() - 1, k);}else{return RandomizedSelect(vRight, 0, vRight.size() - 1, k - vLeft.size() - 1);}
}int main()
{vector<int> vec({ 10,2,32,45,21,33,8,36,55,64,12,78,5 });cout << "原序列" << vec;int k = 5;int nV = RandomizedSelect(vec, 0, vec.size() - 1, k);sort(vec.begin(), vec.end());cout << "排序后:" << vec;cout << "第" << k << "小元素为:" << nV << endl;return 0;
}

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

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

相关文章

11.27 模拟赛

复盘 T1 一眼不会。模拟样例的时候好像得到了一个对于每次询问 \(\mathcal O(n)\) 做的暴力算法。不太清楚。 画了点图。差不多得到一点想法。发现用 set 维护连通块,总复杂度 \(\mathcal O(n \log^2 n)\),1e6 肯定过不去。但应该能过 80。写写试试。 然后写了一坨。实际上这…

fastadmin更改上传附件数据库为附件ID

1.后台返回值加入ID application/admin/controller/Ajax.php文件中upload()方法,2处返回值加上附件ID 这样上传文件后,返回值便会多出file_id字段 2.比如添加商品页面 上传商品图,得到file_id;

联想拯救者 Y7000P 2019 PG0 黑苹果

帮小老弟把Y7000P 2019 PG0笔记本安装了黑苹果系统,参考了GITHUB上的一些资料,并对OC EFI进行调整,以兼容macOS15.x参考链接:https://github.com/xiaoMGitHub/LEGION_Y7000Series_Hackintosh/tree/master

Arch linux下把chromeOS安装至btrfs子卷

旧的ChromeOS单独划分一个ext4分区安装,划分的是ChromeOS可用的最大空间,当存储未用满时,这个ChromeOS独占的分区就有很大的浪费。最近Brunch的作者发布了linux安装工具Linuxloops,可以把ChromeOS安装到Btrfs子卷。Linuxloops采用了图形安装界面,不需要提前下载Brunch及Ch…

ZW3DC++调用C#的DLL

C#: using System;using System.Collections.Generic;using System.Text; namespace TestWinform{ public class Class1 {public void openForm() { Form1 form = new Form1(); form.ShowDialog(); }}}C++: #using "C:\\Test…

Windows 10应用商店找回方法

应用商店(Microsoft Store)作为Windows 10系统的重要的组成部分,为用户提供了一个便捷的平台来浏览、下载和安装各类应用程序。 通过Windows PowerShell重新安装应用商店 1:以管理员身份运行Windows PowerShell在Windows 10的任务栏搜索框中输入“Windows PowerShell”。 右…

超详细!Apache Maven下载安装使用教程

前言 在当今的软件开发领域,尤其是基于 Java 平台的项目开发过程中,拥有一款高效、便捷的项目管理工具至关重要。本篇文章将聚焦于在 Windows 10 系统下,为大家详细介绍 Apache Maven 的下载与安装教程,帮助大家轻松上手这款功能强大的工具,更好地管理和构建 Java 项目。 …

新兴数据仓库设计与实践手册:从分层架构到实际应用(三)

本手册将分为三部分发布,以帮助读者逐步深入理解数据仓库的设计与实践。第一部分介绍数据仓库的整体架构概述; 第二部分深入讨论ETL在数仓中的应用理论,ODS层的具体实现与应用; 第三部分将围绕DW数据仓库层、ADS层和数据仓库的整体趋势展开;通过这样的结构,您可以系统地学…

电平标准

一.常见的电平标准有TTL电平标准,RS485电平标准,RS232电平标准 一.TTL电平标准: 逻辑高(1):通常在2.7V以上,典型值为3.3V或5V. 逻辑低(0):通常在0.8V以下,典型值为0V. 二.RS232电平标准: 逻辑高(1):+3V到+15V. 逻辑低(0):-3V到-15V. 三.RS485电平标准: 逻辑高(1…

BUCK变换器功率级分析

1.BUCK变换器 1.1 概述 BUCK变换器(以下简称“BUCK”),其中文名为“非隔离降压式变换器”,它是“三大基本开关拓扑结构”之一,总体来说,正激、推挽、半桥、全桥拓扑都是BUCK的衍生拓扑“相当于BUCK的隔离版本”,BUCK变换器在非隔离功率变换、级联式开关变换器中具有广泛…

synctv在线一起看电影的web应用

可实现多人观看电影,直播 ​​拉取镜像:docker pull synctvorg/synctv:latest一键运行命令:docker run -d --name synctv -p 8080:8080-e PGID=0-e PUID=0-e TZ=Asia/Shanghai-v /vol1/1000/docker/Configs/synctv:/root/.synctv synctvorg/synctv:latest用户名 root 密码 r…

SQLSERVER——XML转数据表输出(E10的PickList转成数据表)

-- 声明 XML 变量并加载 XML 数据 DECLARE @XML AS XML; SET @XML= N<PickListType> <Name>UDF_COLLECTION_TJ</Name> <DisplayName>收款条件</DisplayName> <Items> <PickListItem> <Id>合同签订</I…