今日的算法题涉及到快速排序,然而这不是重点。话不多说我们先看题:
首先看到题,我们的思路是先将这堆无序的数有序排列(这里推荐用快排,因为其他排序可能会超时),排好序后我们再分析,我们的目的是让这些数尽可能多配对,那么现在的问题就在于该如何匹配。
我们定义一个子函数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,今天分享就到这里。
都看到这了,点个赞吧,彦祖!