算法程序设计——找第k小的数

找第k小的数

Time Limit: 1000MSMemory Limit: 65536K
  
Description
     
 

设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数。

 
     
Input
     
 
输入有两行:

第一行是n和k,0<k<=n<=10000

第二行是n个整数
 
     
Output
     
 
输出第k小的数
 
     
Sample Input
     
 
10 4
2 8 9 0 1 3 6 7 8 2
 
     
Sample Output
     
 
2
 
     

    因为本题要求使用O(n)的时间,所以不能直接采用排序然后输出的方法来解题。因此采用分治方法,先任意找数组中的一个元素a(代码中的a为数组的第一个元素,亦可才用随机数选取数组中的任一个元素),采用快速排序将数组进行一次划分,即将小于a的元素放在其左侧,大于a的元素放在其右侧。然后判断元素a是否满足题目为第k小的数,满足则直接输出,否则判断下一次在哪一区间进行划分。


代码:

//找第k小的数
#include <iostream>
using namespace std;

int partition(int a[], int left, int right)
{//将数组a的第left到right个元素进行划分
	int x = a[left];
	
	while (left < right) 
	{//采用快排策略
		while (left < right && a[right] >= x)
			right--;
		a[left] = a[right];
		
		while (left < right && a[left] <= x)
			left++;
		a[right] = a[left];
	}
	
	a[left] = x;
	
	return left;
}

int find(int a[], int left, int right, int k)
{//在数组a的第left到right中寻找第k小的数
	int pos = partition(a, left, right);

	if (k - 1 == pos)
		cout << a[k - 1];
	else if (k - 1 < pos)//判断下一次划分在哪一区间进行
		find(a, left, pos - 1, k);
	else
		find(a, pos + 1, right, k);

	return 0;

}

int main()
{
	int n, k;
	cin >> n >> k;

	int a[1000];
	for (int i = 0; i < n; i++)
		cin >> a[i];

	find(a, 0, n - 1, k);

	return 0;

}






  • 16
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 卫兵布置问题是一道经典的算法问题,涉及到的算法类别为贪心算法。问题描述如下: 有n个卫兵需要布置在一条直线上,每个卫兵可以占据一个整数位置,不同卫兵之间需要保持至少k个单位的间隔。现在给出n和k,求最少需要占据的位置。 解题思路: 首先,我们需要将卫兵按照位置从小到大排序,然后从第一个卫兵开始布置,每次选择离当前卫兵最远的位置,同时要保证与前一个卫兵的距离不小于k。具体实现可以使用一个指针记录上一个卫兵的位置,每次选择下一个卫兵时,从当前位置向后遍历,到第一个满足条件的位置即可。 代码实现: ``` int n, k; int pos[MAXN]; int main() { cin >> n >> k; for (int i = 1; i <= n; i++) { cin >> pos[i]; } sort(pos + 1, pos + n + 1); // 对卫兵位置进行排序 int cnt = 1, last_pos = pos[1]; for (int i = 2; i <= n; i++) { if (pos[i] - last_pos >= k) { // 到满足条件的位置 cnt++; last_pos = pos[i]; } } cout << cnt << endl; return 0; } ``` 该算法时间复杂度为O(nlogn),其n为卫兵的量,主要来自于排序的时间复杂度。 ### 回答2: 卫兵布置问题是一个经典的算法程序设计问题,其目标是在给定的一段城墙上布置最少量的卫兵,使得每个卫兵能够监视到尽可能多的城墙段。假设城墙由n个不同长度的墙段组成,每段墙上可以部署一个卫兵,卫兵的监视范围是以其所在位置为心的一段墙。设计一个算法,计算出最少需要多少个卫兵来覆盖整段城墙。 解决这个问题的一个有效的算法是贪心算法。具体步骤如下: 1. 将城墙段按照从左到右的顺序进行排序,以便后续的贪心策略。 2. 标记第一段城墙为已布置卫兵的区域,同时记录已布置卫兵的量为1。 3. 从第二段城墙开始依次遍历每一段城墙。 4. 若当前城墙段与前面的已布置卫兵的监视范围没有交集,则在该城墙段布置一个卫兵,并将已布置卫兵的量加1。 5. 若当前城墙段与前面的已布置卫兵的监视范围有交集,则不需要再布置卫兵。 6. 继续遍历下一段城墙,重复步骤4和5,直到遍历完所有城墙段。 7. 返回已布置卫兵的量作为最优解。 这个贪心算法时间复杂度为O(nlogn),其n是城墙段的量,主要消耗的时间在于排序城墙段。这个算法的关键在于排序和遍历过程的判断条件,通过贪心的策略,每次都选择覆盖范围最大的城墙段来布置卫兵,从而达到最少布置卫兵的目的。 总之,卫兵布置问题是一个经典的算法程序设计问题,可以通过贪心算法进行解决,其思想是选择覆盖范围最大的城墙段来布置卫兵,从而实现最少布置卫兵的目标。 ### 回答3: 卫兵布置问题是一个有趣的算法程序设计问题。假设有n个卫兵站在一条直线上,间隔相等。现在,需要将m个卡点放在直线上,卡点的位置必须是卫兵所站位置的整数倍。要求卡点之间的间距最小。 我们可以通过以下步骤来解决这个问题: 1. 首先,计算出卫兵的间距,即d = (直线长度) / (卫兵量 - 1)。这个间距将作为卡点之间的最小间距。 2. 然后,将卡点均匀地放置在直线上,首先放置在第一个卫兵所站的位置,然后每隔d的距离放置一个卡点,直到放置m个卡点。 3. 如果m超过了卡点的最大量(即卫兵量-1),则无法到满足条件的解。否则,输出卡点的位置即可。 该算法时间复杂度是O(m)。在实际应用,可以通过输入直线长度和卫兵量来确定卫兵的间距和卡点的位置,然后根据需求决定是否继续放置卡点。这样,可以在保证卡点之间的最小间距的前提下,灵活地调整卫兵和卡点的量,以满足各种要求。 总之,卫兵布置问题是一个简单且有趣的算法程序设计问题,通过计算卫兵的间距和均匀地放置卡点,我们可以到满足条件的解。该算法可以应用于各种需要将点均匀地分布在一条直线上的场景

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值