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



