0
点赞
收藏
分享

微信扫一扫

找出数组中第 k 小的数

code_balance 2022-04-14 阅读 131
c++算法

题目:

给定整型数组 S 和整数 k,S的长度为n,1<= k <= n,请输出数组中第 k 小的数。

输入的第一行为数组 S 的各个元素,输入的第二行为整数 k。

测试案例(1):

我相信大家的第一想法都是是给数组排完序后直接选取。不过排序的时间复杂度最低是O\left ( nlogn \right ),而如果使用分治法,我们可以将时间复杂度降为线性。伪代码如下:

我的理解是:将所有数字5个为一组,分成若干组。选取每个组中中间大小的数存入一个中间数数组,之后再取中间数数组的中间数,将其定为一个标点。以此标点对整个数组进行分类,分为大于、小于还有等于。完成后再递归进各类,重复以上工作直到触及边界条件。

代码如下:


#include<iostream>
#include<queue>
using namespace std;
void Buddlesort(int a[], int start, int end)//自定义排序,以便给数组进行部分排序
{
	for (int i = start;i <= end;i++)
	{
		for (int j = start;j <= end;j++)
		{
			if (a[i] < a[j])
				swap(a[i], a[j]);
		}
	}
}

int select(int a[], int start, int end, int k)
{

	int n = end - start;//获取大小,end为数组长度,即最后一位下标加1

	if (n <= 5)//界定边界情况
	{
		Buddlesort(a, start, end-1);
		return a[start+k-1];
	}

	int arraynum = n / 5;//5个一组,获取组数
	int* m = new int[arraynum];//创建中位数数组
	for (int i = 0;i < arraynum;i++)
	{
		Buddlesort(a, start + i * 5, start + i * 5 + 4);
		m[i] = a[start + i * 5 + 2];
	}
	Buddlesort(m, 0, arraynum - 1);//中位数数组排序
	int mid = m[arraynum / 2];//取中位数数组中位数以作标点

	int* a1 = new int[n];//设立三数组用于收录比标点大、 小、等于三种情况的数
	int* a2 = new int[n];
	int* a3 = new int[n];
	int num1 = 0;
	int num2 = 0;
	int num3 = 0;
	for (int i = start;i < end;i++)
	{
		if (a[i] < mid)//小于标点进数组1,以下类推
			a1[num1++] = a[i];
		else if (a[i] == mid)
			a2[num2++] = a[i];
		else
			a3[num3++] = a[i];
	}
	if (k <= num1)
		return select(a1, 0, num1, k);
	else if (k <= num1 + num2)
		return mid;
	else
		return select(a3, 0, num3, k - num1 - num2);
}
int main()
{
	int a = 0;
	queue<int>mynum;
	while (cin >> a)//利用STL队列动态输入,队列最后一位为所求k值
	{
		mynum.push(a);
	}
	int k = 0;
	k = mynum.back();
	int n = mynum.size() - 1;
	int*arr =new int[n];
	int i = 0;
	for(i=0;i<n;i++)
	{
		arr[i] = mynum.front();
		mynum.pop();
	}
	cout << select(arr, 0, n, k);
	system("pause");
}

(文中各图摘自《算法设计与分析(第2版)》)

举报

相关推荐

0 条评论