
一、题目简介
1. 题目链接
洛谷 P1116 车厢重组(普及 -) https://www.luogu.com.cn/problem/P1116
2. 题意描述
有一列编号混乱的火车车厢,我们只能交换相邻两节车厢。 规定:每一次相邻交换,算作 1 次操作。 求:将整个车厢序列从小到大排序,需要的最少操作次数。
3. 输入输出格式
输入:
- 第一行:整数 n 代表车厢数量
- 第二行:n 个整数,表示当前车厢的混乱序列
输出:
- 一个整数:最少相邻交换次数
4. 数据范围
,数据规模较小,完全可以用冒泡排序暴力通过。
二、核心难点推理(全文最重要)
1. 什么是逆序对?

简单直白理解:前面的数比后面的数大,就是逆序对。
示例:序列 3 2 1 逆序对包含:(3,2)、(3,1)、(2,1) → 共计 3 组
2. 关键结论(本题核心真理)
只允许相邻交换时,排序的最少交换次数 = 整个序列的逆序对总数
3. 为什么一定相等?(完整逻辑推理)
我们单独分析一次相邻交换的作用: 假设存在相邻逆序组合:5 3 两者交换后变为有序组合:3 5
可以得出核心规律:每一次相邻交换,有且仅有一组逆序对被消除,不会多、不会少。
想要让整个无序序列变为完全升序,必须清空序列中所有逆序对。 因此最终推导公式:排序最小相邻交换次数 = 序列逆序对总数量
三、解题算法:冒泡排序
1. 冒泡排序核心原理
冒泡排序是入门级基础排序算法,核心规则:
- 反复遍历数组,仅比较相邻两个元素
- 若前元素大于后元素,直接交换两者位置
- 每一轮遍历,都会将当前未排序区间的最大值冒泡至区间最右侧
本题的限制是只能相邻交换,而冒泡排序的所有操作都是纯相邻交换,完美贴合题目规则。 因此我们只需要统计冒泡排序过程中,所有的交换次数,得到的结果就是本题答案。
2. 双层循环结构详解
// 外层:一共 n-1 轮冒泡
for(int i=1;i<=n-1;i++)
{
// 内层:只遍历未排序区域
// 后面 i 个已经排好序,不用再比
for(int j=1;j<=n-i;j++)
{
// 发现逆序,相邻交换
if(a[j]>a[j+1])
{
swap(a[j],a[j+1]);
cnt++; // 统计交换次数
}
}
}
- 外层 i:控制冒泡总轮次,n 个元素最多执行 n-1 轮即可完全有序
- 内层 j:每轮只需遍历前 n-i 个元素,右侧 i 个元素已经排序完成,无需重复比较
- cnt 计数器:累计所有相邻交换次数,等价于统计逆序对总数
四、完整过程模拟(手把手看懂)
以样例:n=3,序列:3 2 1 为例 初始状态:cnt = 0
第一轮冒泡(i=1):末尾 1 个数就位
- j=1:3>2,交换,序列变为
[2,3,1],cnt=1 - j=2:3>1,交换,序列变为
[2,1,3],cnt=2 本轮结束,全局最大值 3 归位末尾。
第二轮冒泡(i=2):末尾 2 个数就位
- j=1:2>1,交换,序列变为
[1,2,3],cnt=3
数组完全有序,循环结束。 最终答案:3,与序列逆序对数量完全一致。
五、可直接 AC 的完整代码(超详细注释)
#include <iostream>
using namespace std;
// n最大1000,开1005防止数组越界
const int N = 1005;
int a[N];
int main()
{
int n;
int cnt = 0; // 统计交换次数(逆序对总数)
cin >> n;
// 读入车厢序列
for(int i = 1; i <= n; i++)
{
cin >> a[i];
}
// 冒泡排序核心逻辑
for(int i = 1; i <= n - 1; i++)
{
// 每轮只遍历未排序区间
for(int j = 1; j <= n - i; j++)
{
// 检测到逆序对,执行相邻交换
if(a[j] > a[j+1])
{
swap(a[j], a[j+1]);
cnt++;
}
}
}
// 输出最小操作次数
cout << cnt << endl;
return 0;
}
六、算法复杂度分析
- 时间复杂度:

- 适用范围:本题
,运算量极低,洛谷评测数据稳过 - 空间复杂度:
,仅需一维数组存储数据,无额外空间消耗
七、知识点总结与拓展
1. 本题核心考点
冒泡排序算法运用 + 逆序对概念理解 + 贪心最小操作逻辑推导,是编程初学者打通排序算法底层逻辑的经典入门题。
2. 必背核心结论
- 只能相邻交换时:数组排序最小交换次数 = 逆序对数量
- 每一次合法相邻交换,有且仅消除一组逆序对
3. 进阶优化(拔高拓展)

八、写在最后
绝大多数新手做这道题,只会机械默写冒泡代码,却不懂交换次数为什么就是答案。
通过本篇题解可以彻底吃透核心逻辑:冒泡排序的每一次相邻交换,本质都是在消除一组逆序对,这也是本题的解题灵魂。
掌握这个结论后,所有「仅相邻交换、求最小排序次数」的题目,都可以直接秒解。


被折叠的 条评论
为什么被折叠?



