计算序列第 k 小的元素【算法设计与分析】

实验问题:

给定一个序列,求出此序列第k小的元素

问题分析:

可以利用快速排序,随机取一个元素将比它小的数放在它的右边,

比它大的数放在左边。根据左子集的元素个数可以分为三种情况:

第一种:nleft=k-1 那么分界数据即为问题的答案;

第二种:nleft>k-1 那么第k小的数存在于左子集中问题规模减小;

第三种:nleft<k-1 那么第k小的数存在于右子集中,问题变为选择第k-nleft-1小的数。

数学建模:

建立函数get_kSmall(arr,begin,end,k)其中arr是开始输入的数组,begin是数列的首指针,end是数列的尾指针,k是要求的第k小的数。

开始进行快速排序,随机找一个数arr[begin],以这个数为基准,大于此数放右边,小于此数放左边。

最后得到arr[begin]这个数所处在序列的位置i。接着判断i与k-1之间的大小,如果等于则返回arr[i];如果大于,继续在左子集中寻找即get_kSmall(arr,begin,i-1,k);如果小于,继续在右子集中寻找,即get_kSmall(arr,i+1,end,k-i-1)。

递归出口是k<=1或者i=k-1。

实验代码:

//计算序列第K大的元素
//采用分治法(减治法),快速排序方法

#define _CRT_NO_SECURE_WARNINGS

#include<stdio.h>
#include<iostream>

using namespace std;

int get_kBig(int* arr, int begin, int end, int k) {
	if (begin < end) {
		//随机取一个数为基准
		int temp = arr[begin];
		//i,j指针移动
		int i = begin;
		int j = end;
		while (i < j) {
			//从序列左边开始对比
			//大于temp则j左移
			while (i<j && arr[j]>temp) {
				j--;
			}
			//找到小于temp值则将此值填在arr[i]
			arr[i] = arr[j];
			while (i < j && arr[i] <= temp) {
				i++;
			}
			arr[j] = arr[i];
		}
		//将临时的值填在特定位置
		arr[i] = temp;
		//第k小值即为temp
		if (i == k - 1) {
			return arr[i];
		}
		//第k小值在temp的右边
		else if (i > k - 1) {
			return get_kBig(arr, begin, i, k);
		}
		//第k小值在temp左边且问题规模减小
		else {
			return get_kBig(arr, i + 1, end, k - i - 1);
		}
	}
}

int main() {
	int arr[100] = { 0 };
	int k = 0;
	int i = 0;
	int output;
	cout << "请输入要求解的数组:";
	for (i = 0;i < 100;i++) {
		cin >> arr[i];
		if (getchar() == '\n') {
			break;
		}
	}
	cout << "请输入求其第几大的数:";
	cin >> k;

	output = get_kBig(arr, 0, i, k);
	cout << "此数为:" << output << endl;
	system("pause");
	return 0;
}

实验结果:

时间复杂度分析:

最坏复杂度是O(

平均复杂度是O(n)

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以使用快速选择算法来寻找一个序列第k小的元素。该算法的思路是选取一个基准元素,将序列分成两个部分,小于基准元素的放在一边,大于基准元素的放在另一边,然后根据基准元素所在的位置与k的大小关系,递归地在其一个部分查找第k小的元素。 具体实现过程如下: 1.随机选取一个元素作为基准元素pivot。 2.将序列小于等于pivot的元素放在左边,大于pivot的元素放在右边。 3.判断pivot所在的位置和k的大小关系: a.如果pivot的位置小于k,则在右边的序列继续寻找第k-pivot位置的元素。 b.如果pivot的位置大于k,则在左边的序列继续寻找第k个元素。 c.如果pivot的位置等于k,则返回pivot。 4.重复以上步骤,直到找到第k小的元素。 下面是使用Python实现的快速选择算法代码: ```python import random def quick_select(arr, k): if len(arr) == 1: # 当序列只有一个元素时直接返回 return arr[0] pivot = random.choice(arr) # 随机选取一个元素作为基准元素 left = [x for x in arr if x < pivot] right = [x for x in arr if x > pivot] pivot_pos = len(left) + 1 # 计算pivot在序列的位置 if k == pivot_pos: return pivot elif k < pivot_pos: return quick_select(left, k) else: return quick_select(right, k - pivot_pos) ``` 使用示例: ```python arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5] k = 4 print(quick_select(arr, k)) # 输出第4小的元素,应该为3 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

粒粒米z

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

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

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

打赏作者

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

抵扣说明:

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

余额充值