鱼C论坛

 找回密码
 立即注册
查看: 19|回复: 1

这个冒泡到底哪里有问题

[复制链接]
发表于 6 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
新生入学后,图书馆将
N
N 本书摆在一条书架上。书的编号为
1
,
2
,
…
,
N
1,2,…,N。

目前,这些书的顺序可能是乱的。管理员希望通过调整书的位置,使书架最终变为:第
1
1 个位置放编号
1
1 的书,第
2
2 个位置放编号
2
2 的书,依次类推。

书架前安装了一台轨道机械臂。每次操作时,小蓝可以选择三个连续的位置,机械臂会交换第一个位置和第三个位置上的书,中间位置上的书保持不动。

例如,当前书架顺序为
1
,
2
,
3
,
4
,
5
1,2,3,4,5。选择第
2
2 至第
4
4 个位置后,编号为
2
2 和
4
4 的书会交换,书架变为
1
,
4
,
3
,
2
,
5
1,4,3,2,5。

现在给出书架上
N
N 本书的当前顺序,请你计算,至少需要进行多少次操作,才能将书架恢复为
1
,
2
,
…
,
N
1,2,…,N 的顺序。如果无论如何都无法完成,输出
−
1
−1。


#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int n ;
  scanf("%d",&n);
  long long a[100005];
  for(int i = 0; i < n; i++)
  {
    scanf("%lld",  &a[i]);
    if(a[i] % 2 != (i + 1) % 2)
      break;
      printf("-1");
    return 0;
  }
  long long ans = 0;
  for(int j = 0; j < n - 2; j++)
  {
    for(int i = 0; i < n - 2; i++)
    if(a[i] > a[i + 2])
    {
      long long t = a[i];
      a[i] = a[i + 2];
      a[i + 2] = t ;
      ans++;
    }
  }

  printf("%lld", ans);
  return 0;
}
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 6 天前 | 显示全部楼层
你的代码主要有这些问题:
  • a 只是一个变量,没有数组,读入时每次都覆盖,后面无法比较和交换。
  • 奇偶检查的 if 没有大括号,导致 printf("-1"); return 0; 无论条件如何都会执行,程序读第一个数就退出了。
  • 冒泡里写的是 a > a,自己和自己比,永远不成立;而且交换的也是同一个变量,没有意义。
  • 循环边界 n-2 不对,且没有对数组操作。
  • 不能对整个数组直接冒泡排序。题目每次只能交换距离为 2 的两个位置,也就是只能交换奇数位置之间、偶数位置之间。直接冒泡会交换相邻的奇偶位置,这是不允许的。


正确思路:
每次操作交换位置 i 和 i+2,所以:
1. 位置 i 上的书必须和 i 同奇偶,否则无解,输出 -1。
2. 奇数位置上的书只会互相交换,偶数位置上的书也只会互相交换。
3. 最少操作次数 = 奇数位置序列变成升序的逆序数 + 偶数位置序列变成升序的逆序数。

参考代码(用归并排序求逆序数,O(N log N)):

  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. long long merge(int a[], int tmp[], int l, int r) {
  4.     if (l >= r) return 0;
  5.     int mid = (l + r) / 2;
  6.     long long cnt = merge(a, tmp, l, mid) + merge(a, tmp, mid + 1, r);
  7.     int i = l, j = mid + 1, k = l;
  8.     while (i <= mid && j <= r) {
  9.         if (a[i] <= a[j]) tmp[k++] = a[i++];
  10.         else {
  11.             tmp[k++] = a[j++];
  12.             cnt += mid - i + 1;
  13.         }
  14.     }
  15.     while (i <= mid) tmp[k++] = a[i++];
  16.     while (j <= r) tmp[k++] = a[j++];
  17.     for (i = l; i <= r; i++) a[i] = tmp[i];
  18.     return cnt;
  19. }

  20. int main() {
  21.     int n;
  22.     scanf("%d", &n);
  23.     int *a = (int*)malloc((n + 1) * sizeof(int));
  24.     for (int i = 1; i <= n; i++) {
  25.         scanf("%d", &a[i]);
  26.         if (a[i] % 2 != i % 2) {
  27.             printf("-1\n");
  28.             free(a);
  29.             return 0;
  30.         }
  31.     }
  32.     int *odd = (int*)malloc((n / 2 + 2) * sizeof(int));
  33.     int *even = (int*)malloc((n / 2 + 2) * sizeof(int));
  34.     int oc = 0, ec = 0;
  35.     for (int i = 1; i <= n; i++) {
  36.         if (i % 2 == 1) odd[oc++] = a[i];
  37.         else even[ec++] = a[i];
  38.     }
  39.     int *tmp = (int*)malloc((n + 1) * sizeof(int));
  40.     long long ans = merge(odd, tmp, 0, oc - 1) + merge(even, tmp, 0, ec - 1);
  41.     printf("%lld\n", ans);
  42.     free(a); free(odd); free(even); free(tmp);
  43.     return 0;
  44. }
复制代码


如果你的 N 很小,也可以分别对 odd 和 even 写冒泡统计逆序数,但要注意只比较同一序列内的相邻元素。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-10-11 00:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表