最快的方法当然是O(n)了
先桶排一下,知道多少个1,多少个2,多少个3. 这样我就知道,有多少个2和多少个3在1的位置上~
a[i][j]表示,在有多少个i在j的位置上
那么如果tmp = min(a[i][j] , a[j][i]), 显然至少要tmp次才可以把他们这一组数组交换位置。
那么就要进行那么几次配对,把可以直接交换位置的全部交换完毕。 这些是不可能有简单的方法来交换的。
为何我在最后直接,再 ans += (b[0][1] + b[0][2]) * 2;;,就得到答案了呢~?
因为,可以把模型抽象成一个图。 从1即将出去的数字的数量,和要进入1的数字数量一定是等价的。
也就是把1,2,3看成3个顶点。 这3个顶点的入度和出度一定都是一样的。 所以b[0][1] 和b[0][2] 就是从1这个点的出度了。 因为图的特殊性,要不3个都是强联通分量,要不就是连成一个三角形。 所以直接把出度乘以3即可。
/*
TASK:sort3
LANG:C++
*/
#include <stdio.h>
#define min(a, b) (a)<(b)?(a):(b)
const int max_n = 1000;
int n, ans=0, tmp, i, j, a[max_n],b[3][3]={0}, c[3]={0};
int main()
{
freopen("sort3.in", "r", stdin);
freopen("sort3.out", "w", stdout);
scanf("%d", &n);
for (i = 0; i != n; ++ i)
{
scanf("%d", &a[i]);
++ c[--a[i]];
}
for (i = 0; i <c[0]; ++ i) ++ b[0][a[i]];
for (i = c[0] ; i != c[0] + c[1]; ++ i) ++b[1][a[i]];
for (i = c[0] + c[1] ; i != n; ++ i) ++b[2][a[i]];
for (i = 0; i != 2;++ i)
for (j = 1; j != 3; ++ j)
{
if (i == j) continue;;
tmp = min(b[i][j], b[j][i]) ;
b[i][j] -= tmp;
b[j][i] -= tmp;
ans += tmp;
}
ans += (b[0][1] + b[0][2]) * 2;
printf("%d\n",ans);
return 0;
}
下面试试当成逆序对来解决这个题目?