算法题练习

今日的算法题涉及到快速排序,然而这不是重点。话不多说我们先看题:

 

 首先看到题,我们的思路是先将这堆无序的数有序排列(这里推荐用快排,因为其他排序可能会超时),排好序后我们再分析,我们的目的是让这些数尽可能多配对,那么现在的问题就在于该如何匹配。

我们定义一个子函数sort,主函数直接调用就好。

int sort(int a[],int n)
{
	quickSort(arr, 0, n - 1);//快排函数,大家可以自己动动手实现一下
	int i, index,j, num = 0;
	index = n / 2;           
	for (i = 0; i < n / 2; i++)    
	{
		for (j =index; j < n; j++)
		{
			if (a[j] >= 2 * a[i])
			{
				num++;//记录票数
				index = j+1;//下次比较直接从该数的后一个开始
				break;
			}
		}
	}
	num = num + (n - 2 * num);//统计最后总的票数
	return num;
}

在此我采用的方法是将排序好的数组分成A、B两个部分,A部分中的数较小,B中数较大,既然我想尽可能多的匹配,那么我们就应该考虑怎样做才不会浪费最小的和最大的数很明显从A第一个开始,依次向后查找,满足条件,让num++,然后跳出该循环省略不必要的遍历,减少耗时

代码中index的作用,记录本次满足条件数的下标,使下次比较从该数的下一个开始比

这么一来用个好处,减少不变要的遍历(减小时间复杂度,否则可能会导致运行超时,运行超时是真难受啊!)

若配对时直接从两边往中间开始移动(即让最大值和最小值配对),这么操作可能会导致一些能配对的数字被遗漏,造成浪费,这点也很致命,例如1   2   3    4

若从两边开始,则结果为3,但正确结果应该是2

兄弟们在遇到问题的时候,可以多操作几组数,发现问题后就知道该从哪里下手。

代码实现:

#include<stdio.h>
void quickSort(int a[], int start, int end);
int sort(int a[], int n);
int arr[500010];//当数组过大时应放在全局,定义为局部变量可能会栈溢出
int main()
{
	int n;
	int i;
	scanf("%d", &n);
	int num;
	for (i = 0; i < n; i++)
	{
		scanf("%d", &arr[i]);
	}
	num = sort(arr, n);
	printf("%d", num);
	return 0;
}

void quickSort(int a[], int start, int end)
{
	if (start > end)
		return;
	int j, i, temp, t;
	i = start, j = end, temp = a[start];
	while (i < j)
	{
		while (j > i && a[j] >= temp)
			j--;
		while (j > i && a[i] <= temp)
			i++;
		if (i < j)
		{
			t = a[i];
			a[i] = a[j];
			a[j] = t;
		}
	}
	a[start] = a[i];
	a[i] = temp;
	quickSort(a, start, i - 1);
	quickSort(a, i + 1, end);
}
int sort(int a[],int n)
{
	quickSort(arr, 0, n - 1);//快排
	int i, index,j, num = 0;
	index = n / 2;           
	for (i = 0; i < n / 2; i++)    
	{
		for (j =index; j < n; j++)
		{
			if (a[j] >= 2 * a[i])
			{
				num++;
				index = j+1;
				break;
			}
		}
	}
	num = num + (n - 2 * num);
	return num;
}*/

OK,今天分享就到这里。

都看到这了,点个赞吧,彦祖!

 

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值