题目要求构造一个数列,保证 a[i] != i
直接将1-n的数列向后移一位即可
int T,n;
int a[maxn];
int main(){
scanf("%d",&T);
while(T--){
memset(a,-1,sizeof a);
scanf("%d",&n);
for(int i=1;i<n;i++){
a[i] = i+1;
}
a[n] = 1;
for(int i=1;i<n;i++){
printf("%d ",a[i]);
}
printf("%d\n",a[n]);
}
return 0;
}
题目要求输出最小并且只有一个的数字,不存在输出-1
定义一个数组用来记录每个数字出现的次数
然后遍历找到出现一次的数字
再遍历一遍找到这个数字对应原数组下标即可
int T,n;
int a[maxn],b[maxn];
int main(){
scanf("%d",&T);
while(T--){
int ans = -1;
int id = -1;
scanf("%d",&n);
for(int i=1;i<=n;i++) b[i] = 0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[a[i]]++; // 记录每个数字的种数 找到只有一种的那个数
}
for(int i=1;i<=n;i++){
if(b[i] == 1){
id = i; // 记录下只有一种并且最小的数字
break;
}
}
for(int i=1;i<=n;i++){
if(a[i] == id){
ans = i;
break;
}
}
printf("%d\n",ans);
}
return 0;
}
题目要求给定一个序列,选一个固定的数字
每次选取不包含这个数的区间删去
最后保证序列中剩余的全部都是一开始选定的数字
问最少的操作次数
我们可以把序列分成好几段,去记录相同数字的段数
例如序列 1 2 3 2 2 2 1
数字1的段数就是2 数字2的段数是2 数字3的段数是1
这样我们就可以发现如果选定数字是1
操作次数就是数字1的段数-1
如果选定数字是2
操作次数就是数字2的段数+1
如果将序列改成1 2 3 2 2 2 3
那么如果选定数字是3
操作次数就是数字3的段数
总结一下
选定数字1时序列的头尾元素都是1
如果是这样一个序列1 2 3 1 2 1 ,操作次数依旧是数字1的段数-1,所以如果首尾元素相同并且是选定数字的话,操作次数就是选定数字的段数-1
选定数字2时序列头尾元素都不是选定元素
那么此时操作次数就是选定数字的段数+1
选定数字3时序列首尾元素中有一个与选定数字相同
此时的操作次数就是选定数字的段数
int T,n;
int a[maxn],b[maxn],cnt[maxn];
int main(){
scanf("%d",&T);
while(T--){
int ans = INF;
scanf("%d",&n);
for(int i=1;i<=n;i++) cnt[i] = 0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){ // 求每个数的连续块数
cnt[a[i]]++;
while(i+1 <= n && a[i] == a[i+1]) i++;
}
int tmp = 0;
for(int i=1;i<=n;i++){
if(cnt[a[i]] != 0){
if(a[1] == a[n] && a[1] == a[i]){
tmp = cnt[a[i]] - 1;
}else if(a[1] == a[i] || a[n] == a[i]){
tmp = cnt[a[i]];
}else if(a[1] != a[i] && a[n] != a[i]){
tmp = cnt[a[i]] + 1;
}
}
ans = min(ans,tmp);
}
printf("%d\n",ans);
}
return 0;
}