题目描述:
给定 N 张卡片,正面分别写上 1、2、……、N,然后全部翻面,洗牌,在背面分别写上 1、2、……、N。将每张牌的正反两面数字相减(大减小),得到 N 个非负差值,其中是否存在相等的差?
输入格式:
输入第一行给出一个正整数 N(2 ≤ N ≤ 10 000),随后一行给出 1 到 N 的一个洗牌后的排列,第 i 个数表示正面写了 i 的那张卡片背面的数字。
输出格式:
按照“差值 重复次数”的格式从大到小输出重复的差值及其重复的次数,每行输出一个结果。
输入样例:
8
3 5 8 6 2 1 4 7
输出样例:
5 2
3 3
2 2
解题思路:
1、使用数组aw[i]存放第i张卡片背后的数字;使用数组bw[i]存放第i张卡片正反两面的数字差值;
2、使用数组cw[]存放数组aw中重复的数字,即重复的差值;使用数组sw[]存放重复差值的个数;存值时,数组cw[]与数组sw[]的下标保持一致;
3、对数组cw[]从大到小排序,存放重复差值个数的数组sw[]的顺序与数组cw[]做同步改变,以保证存放差值和差值个数的数组对应。
由于数组sw[]初始值为0,实际数组存放的值比重复差值的个数小1,输出的时候值要加1。
代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n,i,j,t,c,q,p,flag;
int aw[100000],bw[100000],cw[100000];
int sw[100000]={0};
q=1;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&t);
flag=0;
aw[i]=t;
c=abs(aw[i]-i);
bw[i]=c;
for(p=1;p<q;p++){
if(bw[i]==cw[p]){
sw[p]++;
flag=1;
}
}
if(flag==0){
for(j=1;j<i;j++){
if(bw[i]==bw[j]){
cw[q]=bw[i];
sw[q]++;
q++;
}
}
}
}
for(i=1;i<q-1;i++){
for(j=i+1;j<=q;j++){
if(cw[i]<cw[j]){
t=cw[i];cw[i]=cw[j];cw[j]=t;
t=sw[i];sw[i]=sw[j];sw[j]=t;
}
}
}
for(i=1;i<q;i++){
printf("%d ",cw[i]);
printf("%d\n",sw[i]+1);
}
return 0;
}