求数组中第k大(小)的值——Random-Select方法的实现(线性期望时间)

Python中的random随机数 Python中的random随机数 random模块,使用前需要导入 import random 常用方法 randint(a,b)->int 在取值范围[a,b]之间随机挑选一个整数返回。 choice(seq)->val 从非空序列的元素中随机挑选一个元素返回。 例如: import random random.choice(range(10)) #从0~9之间水机选择一... 阅读详情

问题

在含有n个互不相同的元素的数组中,求得第k小的元素。

Input:int []a,int k
Output: int x

解决思路

特殊情况

k=n,即求最大值
k=1,即求最小值。
对于这两种特殊的情况,可以选择“打擂台”算法:
首先声明一个Max(Min),循环遍历整个数组,若比当前Max(Min)大(小),替换之,最终的Max(Min)即为所求。这个方法比较简单,不再代码赘述。

一般情况

采用的策略是分治法,利用快排的随机划分:

  • 将a[p....r]分为:a[p...q-1]<a[q]<a[q+1...r]
  • if(i==q) return a[q]
  • if(i<q) 在左边子区间a[p...q-1]继续寻找第i小元素
  • else 在右边子区间a[q+1...r]继续寻找第(i-q)小元素

代码

版本一:固定划分元的普通划分(0<=i<=a.length−1)(0<=i<=a.length-1)(0<=i<=a.length−1)
	private int Partition(int[] a, int p, int r) {
		// TODO Auto-generated method stub
		int base = a[r];// 基准元素选最后一个
		int i = p - 1;
		for (int j = p; j <= r - 1; j++) {
			if (a[j] <= base) {// 小于基准元素
				i++;
				swap(a, i, j);
			}
		}
		// 划分完成,将基准元素归位
		swap(a, i + 1, r);
		return i + 1;//这里返回的是确定位置的元素的下标,此时的a[i+1]是数组中第i+1小的元素
	}
	public int GetIthMinNumber(int[] a, int p, int r, int i) {
			if (p == r)
				return a[p];
			int q = Partition(a, p, r);// 得到了第q小的数
			if (i == q)//如果q==i
				return a[q];
			else if (i < q) {//i<q,在左区间继续寻找第i小的元素
				return GetIthMinNumber(a, p, q - 1, i);
			} else//否则 i>q,在右区间寻找第i-p小的数,因为已经找到第q小的数,再找(i-q)个就可以了
				return GetIthMinNumber(a, q + 1, r, i - q);
		}
	private void swap(int a[], int i, int j) {
			// TODO Auto-generated method stub
			int tmp = a[i];
			a[i] = a[j];
			a[j] = tmp;
		}
版本二:随机划分(1<=i<=a.length)(1<=i<=a.length)(1<=i<=a.length)

将Partition方法换成了RandomPartition方法,以下是在Class Sort中的方法

	private int RandomPartition(int[] a, int p, int r) {
			// TODO Auto-generated method stub
			// random.nextInt(x)方法产生的是[0,x)的整数,左闭右开
			//基准元素随机选择区间内的一个,然后交换随机选出的基准元素与最后一个元素的位置,
			//后面操作就与Partition方法相同
			int rand = random.nextInt(r - p + 1);
			rand += p;
			swap(a, rand, r);
			return Partition(a, p, r);
		}
	private int Partition(int[] a, int p, int r) {
		// TODO Auto-generated method stub
		int base = a[r];// 基准元素选最后一个
		int i = p - 1;
		for (int j = p; j <= r - 1; j++) {
			if (a[j] <= base) {// 小于基准元素
				i++;
				swap(a, i, j);
			}
		}
		// 划分完成,将基准元素归位
		swap(a, i + 1, r);
		return i + 1;//这里返回的是确定位置的元素的下标,此时的a[i+1]是数组中第i+1小的元素
	}
	private void swap(int a[], int i, int j) {
			// TODO Auto-generated method stub
			int tmp = a[i];
			a[i] = a[j];
			a[j] = tmp;
		}

重点是这个方法:

/**
	 * 选择数组中第i小的元素(1<=i<=length)
	 * 
	 * @param A
	 * @param p
	 * @param r
	 * @param i
	 * @return
	 */
	int Random_Select(int[] A, int p, int r, int i)// 随机选择
	{
		if (p == r)
			return A[p];
		int q = Partition(A, p, r);
		int k = q - p + 1;//k为左区间的长度,再加上基准元素p这一个元素。相当于找出了前k小的元素
		if (k == i)//如果k==i
			return A[q];
		else if (i < k)
			return Random_Select(A, p, q - 1, i);
		else
			return Random_Select(A, q + 1, r, i - k);// 当在右侧时,注意修改下一次i值

	}

运行结果

测试

public class HelloWorld {
	public static void main(String[] args) {
		int a[] = { 1,5,4,2,34,7,56,8,12,45,76,3 };
		Sort st = new Sort();
//		st.RandomQuickSort(a, 0, a.length-1);
		for(int i:a) System.out.print(i+" ");
//		System.out.println(st.Random_Select(a, 0, a.length-1, a.length-1));
		for(int i=0;i<a.length;i++)
			System.out.println("\n第"+(i+1)+"小的元素是:"+st.GetIthMaxNumber(a, 0, a.length-1,i));//版本1
//		System.out.println("\n第"+(i+1)+"小的元素是:"+st.Random_Select(a, 0, a.length-1,i+1)); //版本二
	}
}	

在这里插入图片描述
两种方法都可以正确运行。
有个问题是,将版本一中的划分方法改为使用随机划分,偶尔会出现错误java.lang.IllegalArgumentException: bound must be positive还没有找到原因。

3DMAX随机选择神器RandomSelect插件使用方法 3DMAX随机选择神器RandomSelect插件使用教程 阅读详情

相关推荐

线性时间求第i大的数,O(n)时间求中位数

用c++实现的平均O(n)时间和最坏O(n)时间求数组中第i大的数

random模块常用命令

【代码】random模块常用命令。

紫微斗数象法奥义ZWDStudy 338

3DMAX随机选择神器RandomSelect插件下载

3DMAX随机选择神器RandomSelect插件,一键随机选择,支持对象、子对象(顶点、边、边界、多边形和元素)多种类型的随机选择。

random selection

转自算法导论中文版第9.2节 线性时间期望的选择算法 randomized-select的期望运行时间为Θ(n)。该算饭是一个随机算法,只处理划分的一边。 伪代码 RANDOMIZED-SELECT(A, p, r, i) 1    if p = r 2        then return A[p] 3    q = RANDOMIZED-PARTATION

liken的专栏 2533

codesys【modbusRTU】主站

【代码】modbusRTU【codesys】

cfqq1989的博客 4371

多旋翼飞行器设计与控制·Pixhawk4以及外部设备接线(笔记004)

笔记主要来源:Pixhawk 4 接线快速入门 目录 一、Pixhawk 4 的各个接口 二、接线图概览(重要传感器及外围设备) 三、飞控、GPS的安装和方向 四、电源 五、无线电遥控 六、数传电台(可选) 七、SD Card(可选) 八、电机以及其他外设 一、Pixhawk 4 的各个接口 FMU:Flight Management Unit 飞行管理组件 主 FMU 处理器:STM32F765 32 位 Arm® Cortex®-M7,216MHz,2MB...

猪猪的博客 1万+

Random_QuickSort

#include "stdafx.h"int PARTITION(int a[], int p, int r) //以递增顺序排序 { int x = a[r]; int i = p - 1; for (int j = p; j < r; ++j) { if (a[j]

huanle543的博客 559

MATLAB 论文复现——基于虚拟储能的电动汽车充放电调度策略及激励评价

文章基于虚拟储能聚合体仿真模型优化电动汽车充放电调度,并采用复合权重评价电动汽车的充电激励。根据电动汽车灵活性和系统稳定性衡量其贡献大小,并通过模糊推理系统模拟用户的充电意愿,实现对电动汽车充电的引导和优化。[1]陈朔,胡昊,方慧敏,等.基于虚拟储能的电动汽车充放电调度策略及激励评价[J/OL].系统仿真学报,1-12[2024-07-24].https://doi.org/10.16182/j.issn1004731x.joss.23-1316.基于虚拟储能的电动汽车充放电调度策略及激励评价。

sjr1478的博客 363

期望为线性的选择算法

平时,我们在做从一堆没有排序的数中,

muzixuanhan的专栏 1486

Win11下Python脚本不执行?5分钟搞定PATH环境变量配置(VSCode终端实测)

本文针对Win11系统下VSCode终端中Python脚本执行无响应的问题,提供了详细的诊断与解决方案。核心在于正确配置PATH环境变量,通过图形化界面调整Python路径优先级,并分享了VSCode终端环境变量的刷新技巧,帮助开发者在5分钟内快速解决环境配置难题。

weixin_28358083的博客 384

4、高光图像滤镜显著改善文本图像的光学字符识别

本文介绍了高光图像滤镜在光学字符识别(OCR)中的应用,详细探讨了其技术原理、实现步骤和在多种场景下的效果。通过增强文本图像的边缘和对比度,高光滤镜显著提升了OCR的识别率,尤其适用于扫描文档、手写笔记和低质量图像。实验结果表明,该方法在不同类型的文本图像中均表现出色,并提出了未来优化方向,如深度学习集成和多模态融合,为OCR技术的发展提供了新的可能性。

ooo22的博客 94

线性时间选择算法Randomized_Select

假设输入数据是互异的。Randomized_Select算法以快速排序算法为模型,可以求一个数组中第k小的元素。与快速排序不同的是,快速排序会递归处理划分的两边,而Randomized_Select只处理划分的一边,期望运行时间为O(n)。#include <iostream> #include <random> using namespace std; int Random(int p,int r

幸福在望 2367

3 路由引入

在大型企业网络中,网络规模十分庞大,选用单一的路由协议无法满足网络的需求,因此多种路由协议共存的情况十分常见。或者出于业务逻辑或行政管理的考虑,会在不同的网络结构中设计和部署不同的路由协议,使路由的层次结构更加清晰可控。路由引入是具有方向性的,将路由信息从路由协议A引入到路由协议B(A-to-B),则路由协议B可获知A中的路由信息,但是此时,A还并不知晓B路由协议中的路由信息,除非配置B-to-A的路由引入。表3-1:各种路由协议的优先级。通过路由引入,可以实现路由信息在不同路由协议间传递。

lwljh134的博客 621

CLRS 9.2期望为线性时间的选择算法

练习9.2-1、9.2-2、9.2-3、9.2-4

我的专栏 722

基于机器学习的网络入侵检测系统设计与实现

本文设计并实现了一个基于机器学习的网络入侵检测系统,采用随机森林模型结合KMM算法优化,使用CICIDS2017数据集进行训练。系统包含完整的数据预处理流程、特征工程、模型调优和远程部署方案。实验结果表明,该系统能有效识别多种网络攻击类型,在检测准确率和误报率方面表现优异。研究为网络安全防护提供了新的技术思路和实用工具,具有重要的应用价值。

huanghm88的专栏 318

LeRobot 入门教程(十一)π0(Pi0)π0.5(Pi0.5)训练、推理、部署

本文介绍了Physical Intelligence公司开发的π₀和π₀.₅系列通用机器人控制视觉-语言-动作模型。π₀作为首款基础模型,融合流匹配、跨实体训练等技术,支持50Hz高频控制。π₀.₅是其升级版,通过异构数据协同训练解决开放世界泛化问题,在Libero基准测试中表现优异。文章详细说明了两个模型的安装要求、使用方法、训练策略及关键参数配置,包括混合精度训练、梯度检查点等优化技术,为机器人在多样化场景中的语义理解和动作控制提供了完整解决方案。

2506_90492529的博客 5036

线性选择算法 .

在期望的线性时间内,可以找到顺序统计量,特别是中位数. 在最坏的情况下,时间依然是线性的.选择问题定义,实际上所有处理均可以推广到集合中包含重复数值的情形。输入:一个包含n个(不同的)数的集合A和一个数i,1<=i<=n。输出:元素x属于A,它恰大于A中其他的i-1个元素。 1、最大值最小值针对一个序列取得最大和最小值均需要n-1次比较。这是一个下限,确定最大值或者最小值的算法可以看作各个元素之间

周健华的专栏 1321

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

《算法导论》第9章-中位数和顺序统计量 9.1-最小值和最大值;9.2-期望为线性时间的选择算法;9.3最坏情况为线性时间的选择算法

本文为《算法导论》第9章 中位数和顺序统计量以及选择算法相关内容,欢迎参考。

Toby的博客 729

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

线性选择算法

选择问题定义,实际上所有处理均可以推广到集合中包含重复数值的情形。 输入:一个包含n个(不同的)数的集合A和一个数i,1<=i<=n。 输出:元素x属于A,它恰大于A中其他的i-1个元素。 1、最大值最小值 针对一个序列取得最大和最小值均需要n-1次比较。这是一个下限,确定最大值或者最小值的算法可以看作各个元素之间一场锦标赛,每次...

aai7747的博客 453

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

期望为线性时间的选择算法

将输入数组进行递归划分,只递归调用一边,假设数组A[p..r]中的元素都不同,返回数组A中第i小的元素,Partition(A,p,r) x = A[r] i = p -1 for j = p to r-1 if A[j] <= x i = i + 1 exchange A[i] with A[j] exchange A[i] with A[j] re...

ailx10 76

《算法导论》CLRS算法C++实现(九)P109 选择数组中第i小(大)的数 顺序统计量...

第九章 中位数和顺序统计学 9.2 以期望线性时间做选择 上一讲是找出最小值,同时找出最大值最小值,以及找出次小值的问题。随意选择数组中第i小(大)的元素看起来要比找最小值的简单选择问题要复杂一些。但是令人惊奇的是,两种问题的渐近运行时间却是相同的,都是O(n)。算法导论上介绍了一种用来解决选择问题的分治算法,即RANDOMIZED-SELECT算法。本算法以快速排序算法的分割算法为基础,如同...

weixin_30568715的博客 152

《算法导论3rd第九章》中位数和顺序统计学

算法导论,第九章,中位数,最大最小值,第K大,顺序统计

懒猫的脚印 1651

选取第k个数据

可以通过

solar一抹阳光的专栏 631

《算法导论》— Chapter 9 中位数和顺序统计学

序在算法导论的第二部分主要探讨了排序和顺序统计学,第六章~第八章讨论了堆排序、快速排序以及三种线性排序算法。该部分的最后一个章节,将讨论顺序统计方面的知识。 在一个由n个元素组成的集合中,第i个顺序统计量是该集合中第i小的元素。正如我们经常遇到的中位数问题,一个中位数是它所在集合中的“中点元素”。对于一个有序元素序列,当元素个数为奇数时,中位数位于 i = (n+ 1)/ 2 位置,当元素个数为偶

指尖飞舞 1042

算法导论读后感-选取数组中的第X小(大)的元素

高效选择算法之选择书祖宗第X小(大)的元素

luanzheng_365的博客 352
上一篇: Linux内核—理解进程创建、可执行文件的加载、以及进程执行、进程切换,重点理解分析fork、execve和进程切换
下一篇: LeetCode——距离顺序排列矩阵单元格
There Is No Code
博客等级 码龄10年 254粉丝 51原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

There Is No Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值