排序算法之:最小交换次数排序(Minimum Swaps to Sort)的图论模型与环分解优化
字数 1433 2025-12-04 17:40:21
排序算法之:最小交换次数排序(Minimum Swaps to Sort)的图论模型与环分解优化
题目描述
给定一个包含 n 个不同元素的数组,每个元素均为整数。每次操作允许交换任意两个元素的位置。问题要求计算出将数组排序所需的最小交换次数。例如,数组 [7, 1, 3, 2, 4, 5, 6] 排序所需的最小交换次数为 5。
解题过程
-
问题分析
直接通过模拟交换过程求解最小交换次数较为困难。关键在于发现:若将数组视为一个置换(每个元素映射到其排序后应在的位置),那么该置换可以分解为若干个不相交的环(cycle)。每个环内的元素通过交换可以归位,且最小交换次数与环的大小密切相关。 -
图论建模
- 将数组索引及其对应的值构建成一个有向图:每个索引 i 指向其值在排序后应处的正确位置 j。
- 例如,数组 [7, 1, 3, 2, 4, 5, 6] 排序后为 [1, 2, 3, 4, 5, 6, 7]。
索引 0(值为 7)应指向排序后 7 的位置(索引 6),索引 1(值为 1)指向排序后 1 的位置(索引 0),依此类推,形成边:0→6, 1→0, 2→2, 3→1, 4→4, 5→5, 6→3。 - 该图会分解为多个环:如 (0→6→3→1→0) 和 (2→2)、(4→4)、(5→5)。
-
环分解与交换次数公式
- 对于每个长度为 k 的环(即环中包含 k 个元素),只需进行 k-1 次交换即可将环内所有元素归位。
- 总最小交换次数 = Σ(每个环的大小 - 1)。
- 上例中,环 (0,6,3,1) 大小为 4,需 3 次交换;环 (2)、(4)、(5) 大小为 1,需 0 次交换。总次数 = 3。
-
算法步骤
- 步骤 1:创建数组的排序副本,记录每个值在排序后的正确位置(可通过哈希表存储值到索引的映射)。
- 步骤 2:初始化一个访问标记数组,记录每个索引是否已被处理。
- 步骤 3:遍历每个索引 i:
- 若 i 已被访问或当前值已在正确位置(即 i 指向自身),跳过。
- 否则,从 i 开始追踪环:沿着边 i → correct_pos[arr[i]] → ... 直到回到 i,记录环中节点数 count。
- 将交换次数增加 count - 1。
- 步骤 4:返回总交换次数。
-
示例演算
数组 arr = [7, 1, 3, 2, 4, 5, 6]:- 排序后为 [1, 2, 3, 4, 5, 6, 7],建立值到位置的映射:{1:0, 2:1, 3:2, 4:3, 5:4, 6:5, 7:6}。
- 从索引 0 开始:
- 当前值 7 的正确位置是 6,从 0→6;
- 索引 6 的值 6 的正确位置是 5,从 6→5;
- 索引 5 的值 5 的正确位置是 4,从 5→4;
- 索引 4 的值 4 的正确位置是 3,从 4→3;
- 索引 3 的值 2 的正确位置是 1,从 3→1;
- 索引 1 的值 1 的正确位置是 0,形成环 (0→6→5→4→3→1→0),大小为 6,交换次数 += 5。
- 剩余索引 2 已指向自身,无需交换。总次数 = 5。
-
复杂度与优化
- 时间复杂度 O(n):每个索引仅被访问一次。
- 空间复杂度 O(n):用于存储位置映射和访问标记。
- 优化点:可在追踪环时直接标记已访问节点,避免重复处理。
关键理解
最小交换次数问题通过图论建模转化为环分解问题,利用“环大小减一”的求和公式高效求解,避免了贪心交换的局部最优陷阱。