算法设计与分析——递归与分治策略——线性时间选择

算法分析与设计-线性时间选择详解(通俗易懂,含图解,附源码)(c++) 线性时间选择 (一)题目 问题描述 给定线性序集中nnn个元素和一个正数kkk,1≤k≤n1\leq k\leq n1≤k≤n,要求找出这nnn个元素中第kkk小的元素 注意:nnn中的元素不重复 (二)解答 1.RandomizedSelect算法 算法思路 在数组a[p:r]a[p:r]a[p:r]中随机找一个数iii将数组划分成两个子数组a[p:i]a[p:i]a[p:i]和a[i+1:r]a[i+1:r]a[i+1:r],如果数组a[p:r]a[p:r]a[p:r]的长度小于等于kkk,说明第kkk 阅读详情

顾名思义:这篇文章讲解的就是如果用线性时间算法来作出元素选择问题。
问题描述:给定线性序集中n个元素和一个整数k,1<=k<=n.要求找出这n个元素中第k小的元素,即如果将这个n个元素依其线性序排列时,排在第k个位置的元素就是要找的元素,当k== 1时,要找的就是最小的元素;当k==n,就是最大的元素;当k=(n+1)/2,称为中位数。

问题分析:
在某些特殊的情况下,我们可以实现线性时间选择,对于找最大最小的元素O(n)内可以实现;当k<=n/logn,通过堆排序算法可以在O(n+klogn)=O(n)内实现;当k>=n-n/logn时也一样。
下面是给出的一般的选择问题,从渐近阶的意义上看,这个也可以在O(n)时间内完成。
下面的算法实现参考了《计算机算法与分析》和一些博客,是对其的一个整理。

方法一:
算法描述:用一个随机的序列中的数作为枢纽,用快速排序算法,进行一次快排,然后将枢纽值和k值进行比较,以此来确定k值,我并没有做任何的对比所以并不是清楚这种算法的效率有多少,但是搜到的结果表明,这种算法的最坏时间复杂度是O(n^2),相对与另一种是不太理想的。

解法:

1.首先大家都会想到的解法是排序,之后找出第k个元素,但是排序的时间复杂度不符合要求,或者需要额外的空间。

2.利用快排的思想,以枢纽(随机得到)为界,将数组分为2部分,一部分小于等于这个枢纽值,一部分大于这个枢纽值,与快排不同的是,我们只处理一部分,另一部分舍弃。

#include<bits/stdc++.h>
using namespace std;

int partition(vector<int> &vec,int left,int right)
{
	int i=left;
	int j=right;
	int temp=vec[left];
	while(i<j)
	{
		while(vec[j]>=temp&&i<j)//处理i,j的先后顺序不能改变 
		{
			j--;
		}
		
		while(vec[i]<=temp&&i<j)
		{
			i++;
		}
		
		swap(vec[i],vec[j]);
	}
	
	vec[left]=vec[j];
	vec[j]=temp;
	
	return j;
}
int  QuickSort(vector<int> &vec,int left,int right,int k)
{
	if(left==right)
		return vec[left];
	
		int mid=partition(vec,left,right);
		int j=mid-left+1;
		if(k<=j)
			return QuickSort(vec,left,mid,k);
		
		else
			return QuickSort(vec,mid+1,right,k-j);
		
		
		
	
}
void print(int x)
{
	cout<<x<<" ";
}



int main()
{
	vector<int> vec={1,2,3,6,5,4,7,8,9};
	for_each(vec.begin(),vec.end(),print);
	cout<<endl;
	int k;
	cout<<"请输入K(要求找出这n个元素中第k小的元素):" ;
	cin>>k;
	int count=vec.size()-1;
	cout<<QuickSort(vec,0,count,k)<<endl;
	QuickSort(vec,0,count,k);
	
	for(auto a:vec)
	{
		cout<<a<<" ";
	}
	cout<<endl;
	
 } 

在这里插入图片描述
方法二:

这里我们就利用中位数来进行线性时间的选择算法!

中位数就是指将数据按大小顺序排列起来,形成一个数列,居于数列中间位置的那个数据就是中位数。

算法思路
(1)将输入的n个数划分成 ⌈n5⌉⌈n5⌉ 个组,当然最后一组的数目可能是小于5的!
(2)用任意的排序方法对他们进行排序,并取出一共 ⌈n5⌉⌈n5⌉ 个中位数。
(3)找出该 ⌈n5⌉⌈n5⌉ 个中位数中的中位数。(如果 ⌈n5⌉⌈n5⌉ 是偶数则取相对大的那个数)
(4)将全部的数划分为两个部分,小于基准的在左边,大于等于基准的放右边。

我们用小圆点表示元素,得到如下图:

在这里插入图片描述

说明:
图中中间白色圈表示各组数据的中位数,最中间灰色表示中位数的中位数! 箭头是从较小的数指向较大的数!

故我们可以使用该数作为划分的基准(比上一个随机基准的方法会好很多)!
在这里插入图片描述

图中
在这里插入图片描述

当n≥75时,3A1大于等于 14n14n。所以按此基准划分所得的左右2个子数组的长度都至少缩短 1414。

#include<bits/stdc++.h>
using namespace std;

int partition(vector<int> &vec,int left,int right,int k)
{
	int i=left;
	int j=right;
	int temp=vec[k];
	while(i<j)
	{
		while(vec[j]>=temp&&i<j)//处理i,j的先后顺序不能改变 
		{
			j--;
		}
		
		while(vec[i]<=temp&&i<j)
		{
			i++;
		}
		
		swap(vec[i],vec[j]);
	}
	
	vec[k]=vec[j];
	vec[j]=temp;
	
	return j;
}

void print(int x)
{
	cout<<x<<" ";
}

int  Select(vector<int> &vec,int left,int right,int k)
{
	if(right-left<75)
	{
		return vec[left+k-1];
	}

	for(int i=0;i<=(right-left-4)/5;i++)
	{
	}
	
		int x=Select(vec,left,left+(right-left-4)/5,(right-left-4)/10);
	
		int i=partition(vec,left,right,x);
		int j=i-left+1;
		
		if(k<=j)
			return Select(vec,left,i,k);
		else
			return Select(vec,i+1,right,k-j);
		
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}

int main()
{
	vector<int> vec={1,2,3,6,5,4,7,8,9};
	for_each(vec.begin(),vec.end(),print);
	cout<<endl;
	int k;
	cout<<"请输入K(要求找出这n个元素中第k小的元素):" ;
	cin>>k;
	int count=vec.size()-1;
	cout<<Select(vec,0,count,k)<<endl;
	Select(vec,0,count,k);
	
	for(auto a:vec)
	{
		cout<<a<<" ";
	}
	cout<<endl;
	
 } 

在这里插入图片描述

计算机算法设计与分析(第4版) 王晓东 著 2012.2 笔记(这本书还不错,偏实用、有难度) 计算机算法设计与分析(第4版) 目录 1 算法概述2 递归与分治策略3 动态规划4 贪心算法5 回溯法6 分支限界法7 随机化算法8 线性规划与网络流 算法概述 复杂性分析NP-完全性理论 递归与分治策略 排列问题:Permutate 注意,递归嵌套在一个函数里,特别选择参数k,k之前的代表已经固定,k之后的依次交换并递归 阅读详情

相关推荐

算法题04:分治法:求第K小元素(线性时间选择算法)

求第k小元素 题目内容: 给定一个线性序列集,要求使用分治法求出其中指定的第 KKK 小的数的值和位置,如给定 nnn 个元素和一个整数 iii,1≤i≤n1≤i≤n1≤i≤n,输出这 nnn 个元素中第 iii 小元素的值及其位置。 一、问题分析(模型、算法设计和正确性证明等) 解决第K小问题有如下几种方法 ①将n个数排序(比如快速排序或归并排序),选取排序后的第k个数,时间复杂度为O(nlog...

宇智波Akali的博客 3万+

【算法设计与分析】递归与分治法:最坏情况下线性时间选择

给定一个包含n个元素的一维线性序列 ,从这n个元素中找出第k小的元素, 。设 ,k = 8,写出最坏情况下用线性时间解决该问题的算法。 1)写出算法实现代码并截屏程序运行结果。 package one; public class two { static int[] a = {2,9,11,3,14,7,10,8,15,4,13,1,6,5,12}; public static void main(String[] args) { System.out.println("调用方法前:");

qq_30260147的博客 797

线性时间选择中位数算法

线性时间选择,中位数算法,利用按每5个元素分组,分别找出其中位数,再递归找出

【计算机算法设计与分析】线性时间选择(C++_分治递归)

问题描述 给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素。 思路 线性时间选择有两种方法: (1)随机选择快排的标准元素。 (2)将集合分为n个由五个元素组成的集合,对每个五元素集合求其中位数,再对所有的五元素集合的中位数求其中位数,作为快排的标准元素。 Code V-1(RandomizedSelect) #include<bits/stdc++.h> #define M 100 using namespace std; int a[M]={6, 7, 5,

ccql's Blog 1657

线性时间选择算法(附完整的代码,结合例题详细解析) 全套资源已打包好,求抱走!!!

给定一个包含n个元素的一维线性序列a[p:r],从这n个元素中找出第k小的元素,1<=k<=n。设a[0:14]={2,9,11,3,14,7,10,8,15,4,13,1,6,5,12},k = 8,采用线性时间选择算法解决该问题。 1)写出算法实现代码并截屏程序运行结果。 2)线性时间选择算法如何解决划分不平衡的问题? 3)分析线性时间选择算法的计算效率。 题目给定了一个包含n个元素的一维线性序列a[0:14]={2,9,11,3,14,7,10,8,15,4,13,1,6,5,12},想要我们求第k小的元素。 注意看,a[0:14]是一个未排序好的数组!那么想要求第k小的元素,我们第一步要干啥?然后呢?接着呢? 第一步:先排序,排成递增数组 第二步:求出结果:a[k]。 嘿,是不是很简单??? 问题来了,题目要求我们使用线性时间选择来求解!!!什么是线性时间选择???为什么要用线性时间选择??? ————————————————

认知网络分析实战:用Python复现课堂对话研究(含LSA代码)

本文通过Python实战,详细演示了如何运用认知网络分析(ENA)和滞后序列分析(LSA)两种方法,对课堂对话数据进行深度挖掘。文章提供了从数据清洗、行为编码到网络构建、序列统计及可视化的完整代码流程,帮助教育研究者和数据分析师量化分析对话中的认知结构与动态互动模式,从而获得超越文本表面的研究洞见。

weixin_28559803的博客 155

线性时间选择(递归与分治算法)

线性时间选择问题:给定一个数组a,找出其中第k小的元素(该算法适合找中位数、最大的数、最小的数等一些特殊元素) int Partition(int *y,int low,int high) { int key=y[low]; while(low<high) { while(low<high && y[high]>=key) high--; y[low]=y[high]; while(low<high && y[low]<key)

weixin_47952737的博客 720

QT的温湿度显示系统

大家好,这里是石侃侃的博客,欢迎前来讨论这篇文章介绍的是DHT11在2440上的基于Qt5.6的应用基于单片机系统的温湿度监测系统构成框图如图2-1所示。图2-1 系统构成框图该系统采用单片机s3c2440作为了本设计的核心元件。利用LCD作为了显示器件,利用触摸屏作为用户界面输入设备,第一行显示当前实时的温度,湿度,第二行依次显示历史时刻最高的温度值,最高的湿度值。第三行是一个文本框,记录了程...

zxpcus的博客 1万+

线性时间选择【递归分治法】

顾名思义:这篇文章讲解的就是如果用线性时间算法来作出元素选择问题。问题描述:给定线性序集中n个元素和一个整数k,1<=k<=n.要求找出这n个元素中第k小的元素,即如果将这个n个元素依其线性序排列时,排在第k个位置的元素就是要找的元素,当k==1时,要找的就是最小的元素;当k==n,就是最大的元素;当k=(n+1)/2,称为中位数。问题分析:在某些特殊的情况下,我们可以实现线性时间选择,对于找最大最

带你飞 9453

​​瑞芯微RK系列 vs 全志系列芯片:终极选型指南(2025版)​

​。

jinxi996611的博客 1万+

PX4固件下VTOL固定翼的3种起飞方式对比:手抛vs弹射vs跑道

本文深度解析PX4固件下VTOL固定翼的三种起飞方式:手抛、弹射与跑道起飞,对比其技术差异与适用场景。通过详细的参数配置和工程实践指南,帮助开发者优化起飞性能,提升无人机在不同环境下的适应性和可靠性。文章特别针对PX4飞控系统的最新特性进行了技术探讨。

weixin_30296405的博客 87

【线性时间选择】“递归与分治策略”——《算法设计与分析(第五版)》

【线性时间选择】“递归与分治策略”——《算法设计与分析(第五版)》

NI‘CE’XIAN‘s blog 468

FPGA图像处理入门 ZYNQ7020 图像中值膨胀腐蚀滤波

图像处理的三种滤波 中值滤波应用较为广泛 综合膨胀和腐蚀可以实现边缘检测。

Coast_的博客 715

第二章、递归与分治策略

第二章、递归与分治策略 二分搜索算法的时间复杂度、大整数乘法、Strassen矩阵乘法、合并排序和快速排序、线性时间选择、最接近点对问题、循环赛日程表。 重点掌握: 递归方程的解(公式法): 分治法的复杂性分析: 其中必须明确n(表示原问题的规模)、m(表示原问题分解为k个子问题后,规模为n/m)、f(n)(表示分解和合并子问题的时间) ########内容############## 二分搜索算法的时间复杂度 2. 大整数乘法(分治法的复杂性分析) 问题导入: 解析: ...

Senye_ing的博客 207

scrapy - 美团民宿 实战练习

目录结构 items.py import scrapy # 民俗名称,地区,价格,房间类型及数量,床的数量,可住几人 class MeituanItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() place = scrapy.Field() price = scrapy.F...

小刘的博客 2664

移动端实战指南:深入理解 & 接入 IAB OMSDK

OMSDK(OpenMeasurementSDK)是IABTechLab推出的标准化测量工具,用于统一移动端/原生App广告的可见性和验证流程。其核心包括Native库(采集设备数据)和OMID JavaScript层(实现通信),通过标准化接口让开发者只需接入一套SDK即可兼容多个测量厂商,减少冲突和性能损耗。v1.4版本强化了对CTV和原生App场景的支持,而v1.5新增了画中画检测等功能。集成流程需通过IAB技术实验室注册下载,并遵循严格的命名空间规则。测试阶段需嵌入验证脚本并通过指定工具验证

帅次的博客 1185

算法设计与分析——期末复习

算法是解决问题的方法与过程。程序可不满足有限性。

weixin_74746867的博客 464

stop pin/ignore pin/exclude pin/float pin

stop pin、ignore pin、exclude pin、float pin的区别

m0_61544122的博客 7288

算法设计与分析复习总结(二)

本文主要介绍了递归与分治策略。

m0_74337962的博客 1087

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

常用算法一(分治算法)

一、基本概念    在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……     任何一个可以用计算机求解的问题所需的计算时

Sun19910114的专栏 441

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

五大常用算法之一:分治算法

分治算法 一、基本概念    在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……     任何一个可以用计算机求解的问题所需的计

小小段同学 1048

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【算法分析与设计】递归与分治策略

计算机算法分析与设计中有关递归与分治策略的讲解,主要包括学习要点、算法总体思想、递归的概念、分治法

東方緋想天 1536

【算法设计与分析】递归与分治策略

本文介绍了递归与分治策略的基本概念和应用。主要内容包括:递归的三要素(基准情况、递归情况、收敛性)及执行过程,比较了递归与迭代的优缺点;分治法的三个步骤(分解、解决、合并)及适用条件,并通过递归树和主定理分析算法复杂度;详细讲解了二分搜索技术,包括迭代和递归两种实现方式。此外还列举了合并排序、快速排序等经典分治算法,为学习更复杂的算法问题奠定基础。

m0_72516377的博客 869
上一篇: 算法设计与分析——递归与分治策略——快速排序
下一篇: 算法设计与分析——递归与分治策略——全排列
943802606
博客等级 码龄6年 1万+粉丝 177原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值