初见这道题,相信很多人跟我一样是想通过寻找数的某种规律来实现选择性的排序,甚至使用全排列暴力解题,但是经过分情况考虑,这种方法需要考虑的情况太多,过于复杂,那么我们不妨从“频率“的角度入手。
首先建一个数组a来装输入的数据,再建一个数组b来记录a中对应元素的”频率“,b数组初始化全为0。
接下来进入正题,比如我们有两个数——2和10。根据题目,210>102,所以2应该放在10之前。因此我们将输入的n个数两两作比较,每次比较后,应该放在前面的那个数的频率+1(也就是b数组中对应的数+1)。这样比较了n-1次后,我们不难发现,有一个数的频率变成了n-1(就是说它应该放在所有数的前面),那么这个数理应放在第一位,还有的数的频率变成了n-2(说明它只应该放在第一个数的后面),那么这个数应该放在第二位...........如此递推,频率的大小也就决定了数据应该放的位置。我们根据a中数据的对应频率给a中数据从大到小排序,依次输出,就是我们想要的结果了。
#include <stdio.h>
#include <math.h>
int posnum(int x)//判断数据位数的函数
{
int i;
for (i = 1; i <= 20; i++)
{
if (x / pow(10, i) < 1)
{
break;
}
}
return i;
}
int main()
{
int n, a[20];
int b[20] = { 0 };
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j < n; j++)
{
if (a[i] * pow(10, posnum(a[j])) + a[j] > a[j] * pow(10, posnum(a[i])) + a[i])
//此循环判断谁该放在前面
{
b[i]++;
}
else
{
b[j]++;
}
}
}
for (int i = 0; i < n - 1; i++)//根据频率(b)从大到小将a排序
{
for (int j = 0; j < n - 1; j++)
{
if (b[j] < b[j + 1])
{
int temp = a[j + 1];
a[j + 1] = a[j];
a[j] = temp;
int temp2 = b[j + 1];
b[j + 1] = b[j];
b[j] = temp2;//别忘了a排序的时候b要跟a同步排序(数据是对应的)
}
}
}
for (int i = 0; i < n; i++)
{
printf("%d", a[i]);
}
}
(该种方法已通过洛谷所有组数据)
如有不对之处,还请多多指正!谢谢!