排序算法之:最小交换次数排序(Minimum Swaps to Sort)的进阶应用:图论模型与环分解优化(深度版)
字数 2189 2025-12-16 02:39:58

排序算法之:最小交换次数排序(Minimum Swaps to Sort)的进阶应用:图论模型与环分解优化(深度版)

题目描述
给定一个由 n 个不同整数 构成的数组 arr,元素取值范围为 1n。每次允许交换任意两个元素。目标是求出将数组按升序排列所需的 最小交换次数

示例
输入:arr = [4, 3, 1, 2]
输出:3
解释:

  • 交换索引0和2 → [1, 3, 4, 2]
  • 交换索引1和3 → [1, 2, 4, 3]
  • 交换索引2和3 → [1, 2, 3, 4],共3次交换。

解题过程
最小交换次数问题可以通过 图论模型 高效解决。关键在于将数组排序转化为 循环分解,并通过环的大小计算交换次数。


第一步:将数组映射为有向图
由于数组元素是 1n 的不同整数,我们可以将数组视为一个 置换(permutation)
定义映射:

  • 当前位置 i(索引从0开始)存放的元素值是 arr[i]
  • 这个元素的 目标位置 应为 arr[i] - 1(因为排序后值 k 应在索引 k-1 处)。

构建有向图:

  • 节点:数组的 n 个位置(索引 0n-1)。
  • 有向边:从 i 指向 arr[i] - 1
    这表示当前位于位置 i 的元素应该被移动到位置 arr[i] - 1 才能到达其最终排序位置。

arr = [4, 3, 1, 2] 为例:

  • 位置0(值4)应去位置3(因为排序后值4应在索引3)。
  • 位置1(值3)应去位置2。
  • 位置2(值1)应去位置0。
  • 位置3(值2)应去位置1。
    边集合:0 → 3, 1 → 2, 2 → 0, 3 → 1

第二步:识别图中的环
在有向图中,由于每个节点有且仅有一条出边和一条入边(因为每个位置对应唯一的目标位置),图会分解为若干个 不相交的有向环

用示例说明:
从节点0出发:0 → 3 → 1 → 2 → 0,形成一个长度为4的环。
(实际上,这个置换只有一个环,包含所有4个节点。)

为什么是环?
因为如果你从某个位置出发,沿着“当前元素的目标位置”一直走,最终会回到起点(路径不会终止,且不会分叉)。这正好构成了一个循环。


第三步:用环计算最小交换次数
关键定理:对于一个长度为 cycle_len 的环,将其中的所有元素归位到正确位置所需的最小交换次数是 cycle_len - 1

解释:

  • 在一个环中,每次交换可以将一个元素放到正确位置,同时将另一个元素移动到环中的下一个位置。
  • 经过 cycle_len - 1 次交换,环中所有元素都归位。
  • 例如,一个长度为1的环(自环)表示该元素已经在正确位置,交换次数为0。

因此,总的最小交换次数 = 所有环的 (cycle_len - 1) 之和。
等价地,设图中有 C 个环,则:
总交换次数 = n - C
(因为每个环贡献 cycle_len - 1,所有环的长度之和为 n,所以总和 = n - C)。

示例验证:

  • 示例中只有一个环,长度 cycle_len = 4C = 1
  • 最小交换次数 = 4 - 1 = 3,与前面一致。

第四步:算法实现
我们可以在 O(n) 时间和 O(1) 额外空间内完成环的检测和计数,不需要显式建图。

具体步骤:

  1. 创建一个 visited 数组(或原地标记)来记录位置是否已被处理。
  2. 遍历每个位置 i
    • 如果 i 已被访问,或 arr[i] 已在正确位置(即 arr[i] == i+1),则跳过。
    • 否则,从 i 开始沿着“目标位置”追踪环:
      • 初始化 cycle_len = 0current = i
      • current 未被访问时:
        • 标记 current 为已访问。
        • current 移动到其目标位置:current = arr[current] - 1
        • cycle_len++
      • 此环对交换次数的贡献为 cycle_len - 1,累加到总结果中。
  3. 返回总交换次数。

优化:可以原地修改数组来标记访问,例如将访问过的位置元素取负数(如果允许修改原数组且元素为正)。


第五步:正确性证明

  • 每次交换可以将一个环的长度减少1(即让一个元素归位),直到整个环被解决。
  • 对于一个长度为 k 的环,至少需要 k-1 次交换(因为最后一次交换会让两个元素同时归位)。
  • 该算法通过追踪环结构,精确计算了这个下界,因此结果是最优的。

第六步:扩展与变体

  1. 包含重复元素的情况:此时图可能不再是简单环,而需要更复杂的处理(例如通过贪心或并查集)。
  2. 最小交换次数使相邻交换:如果只允许交换相邻元素,则转化为逆序对计数问题。
  3. 最小交换次数使数组有序(元素可重复):可通过比较排序后的数组与原始数组,计算环的分解。

总结
将数组排序的最小交换次数问题,通过建立 位置-目标位置 的映射,转化为有向图的环分解。最小交换次数等于 n - C,其中 C 是图中环的数量。这个基于图论模型的方法高效、优雅,且提供了对置换排序的深刻理解。

排序算法之:最小交换次数排序(Minimum Swaps to Sort)的进阶应用:图论模型与环分解优化(深度版) 题目描述 给定一个由 n 个不同整数 构成的数组 arr ,元素取值范围为 1 到 n 。每次允许交换任意两个元素。目标是求出将数组按升序排列所需的 最小交换次数 。 示例 输入: arr = [4, 3, 1, 2] 输出: 3 解释: 交换索引0和2 → [1, 3, 4, 2] 交换索引1和3 → [1, 2, 4, 3] 交换索引2和3 → [1, 2, 3, 4] ,共3次交换。 解题过程 最小交换次数问题可以通过 图论模型 高效解决。关键在于将数组排序转化为 循环分解 ,并通过环的大小计算交换次数。 第一步:将数组映射为有向图 由于数组元素是 1 到 n 的不同整数,我们可以将数组视为一个 置换(permutation) 。 定义映射: 当前位置 i (索引从0开始)存放的元素值是 arr[i] 。 这个元素的 目标位置 应为 arr[i] - 1 (因为排序后值 k 应在索引 k-1 处)。 构建有向图: 节点:数组的 n 个位置(索引 0 到 n-1 )。 有向边:从 i 指向 arr[i] - 1 。 这表示当前位于位置 i 的元素应该被移动到位置 arr[i] - 1 才能到达其最终排序位置。 以 arr = [4, 3, 1, 2] 为例: 位置0(值4)应去位置3(因为排序后值4应在索引3)。 位置1(值3)应去位置2。 位置2(值1)应去位置0。 位置3(值2)应去位置1。 边集合: 0 → 3 , 1 → 2 , 2 → 0 , 3 → 1 。 第二步:识别图中的环 在有向图中,由于每个节点有且仅有一条出边和一条入边(因为每个位置对应唯一的目标位置),图会分解为若干个 不相交的有向环 。 用示例说明: 从节点0出发: 0 → 3 → 1 → 2 → 0 ,形成一个长度为4的环。 (实际上,这个置换只有一个环,包含所有4个节点。) 为什么是环? 因为如果你从某个位置出发,沿着“当前元素的目标位置”一直走,最终会回到起点(路径不会终止,且不会分叉)。这正好构成了一个循环。 第三步:用环计算最小交换次数 关键定理:对于一个长度为 cycle_len 的环,将其中的所有元素归位到正确位置所需的最小交换次数是 cycle_len - 1 。 解释: 在一个环中,每次交换可以将一个元素放到正确位置,同时将另一个元素移动到环中的下一个位置。 经过 cycle_len - 1 次交换,环中所有元素都归位。 例如,一个长度为1的环(自环)表示该元素已经在正确位置,交换次数为0。 因此,总的最小交换次数 = 所有环的 (cycle_len - 1) 之和。 等价地,设图中有 C 个环,则: 总交换次数 = n - C (因为每个环贡献 cycle_len - 1 ,所有环的长度之和为 n ,所以总和 = n - C )。 示例验证: 示例中只有一个环,长度 cycle_len = 4 , C = 1 。 最小交换次数 = 4 - 1 = 3 ,与前面一致。 第四步:算法实现 我们可以在 O(n) 时间和 O(1) 额外空间内完成环的检测和计数,不需要显式建图。 具体步骤: 创建一个 visited 数组(或原地标记)来记录位置是否已被处理。 遍历每个位置 i : 如果 i 已被访问,或 arr[i] 已在正确位置(即 arr[i] == i+1 ),则跳过。 否则,从 i 开始沿着“目标位置”追踪环: 初始化 cycle_len = 0 , current = i 。 当 current 未被访问时: 标记 current 为已访问。 将 current 移动到其目标位置: current = arr[current] - 1 。 cycle_len++ 。 此环对交换次数的贡献为 cycle_len - 1 ,累加到总结果中。 返回总交换次数。 优化:可以原地修改数组来标记访问,例如将访问过的位置元素取负数(如果允许修改原数组且元素为正)。 第五步:正确性证明 每次交换可以将一个环的长度减少1(即让一个元素归位),直到整个环被解决。 对于一个长度为 k 的环,至少需要 k-1 次交换(因为最后一次交换会让两个元素同时归位)。 该算法通过追踪环结构,精确计算了这个下界,因此结果是最优的。 第六步:扩展与变体 包含重复元素的情况 :此时图可能不再是简单环,而需要更复杂的处理(例如通过贪心或并查集)。 最小交换次数使相邻交换 :如果只允许交换相邻元素,则转化为逆序对计数问题。 最小交换次数使数组有序(元素可重复) :可通过比较排序后的数组与原始数组,计算环的分解。 总结 将数组排序的最小交换次数问题,通过建立 位置-目标位置 的映射,转化为有向图的环分解。最小交换次数等于 n - C ,其中 C 是图中环的数量。这个基于图论模型的方法高效、优雅,且提供了对置换排序的深刻理解。