排序算法之:基于“稳定婚姻问题”(Stable Marriage Problem)的Gale-Shapley算法在稳定匹配排序中的应用
题目描述
想象一下这样一个场景:我们需要将两组元素(例如,学生与导师、医院与实习生、职位与申请者)按照他们的“偏好”进行配对。每一边的每个成员对另一边的所有成员都有一个严格的偏好排序列表。目标是找到一个“稳定匹配”——即不存在两对配对 \((A, X)\) 和 \((B, Y)\),使得 \(A\) 比起 \(X\) 更喜欢 \(Y\),并且 \(Y\) 比起 \(B\) 也更喜欢 \(A\)(这种不稳定的“私奔”情况称为“阻塞对”)。经典的 Gale-Shapley 算法(也称为“延迟接受”算法)可以高效地找到一个稳定匹配。本题旨在探讨如何将这个算法或其思想,巧妙地应用于排序问题中,即对一个数组按照某种“偏好”或“优先级”进行重排,使得结果满足某种稳定约束。
核心思想
Gale-Shapley 算法通常用于两组数量相等且偏好列表完整的“双边匹配”问题。在排序问题中,我们可以将排序过程看作一种“匹配”:将数组中的每个元素(想象为一组“求婚者”)与一个“目标位置”(想象为一组“接收方”)进行配对。目标位置对元素的偏好可以由我们希望达成的排序规则(如升序、降序,或更复杂的自定义优先级)来定义。通过构造合适的偏好列表,并运行 Gale-Shapley 算法,我们可以得到一个稳定 matching,从而导出一种满足特定稳定性的排序结果。
解题过程(循序渐进)
第一步:问题转换与偏好列表构造
假设我们要对一个数组 arr 进行升序排序。我们可以将数组的每个元素看作“求婚者”(Proposers),而将数组的每个索引位置(0 到 n-1)看作“接收方”(Receivers,或称为“目标位置”)。
- 求婚者的偏好列表:每个元素(求婚者)的偏好是所有目标位置的一个排序。在升序排序中,我们希望较小的元素占据较小的索引。因此,对于一个元素
value来说,它最希望占据的索引是 0(最小的位置),其次是 1,依此类推。所以,每个元素的偏好列表是所有索引位置按照 0, 1, 2, ..., n-1 的顺序排序。这表示每个元素都同等偏好所有位置? 不,这里需要更精确的映射。
实际上,在标准的稳定婚姻问题中,双方的偏好是基于对方个体的。在这里,我们需要为目标位置(索引)定义其对元素(值)的偏好。一个更自然的映射是:
- 接收方(索引位置 i)的偏好列表:我们希望位置 i 被第 i 小的元素占据。因此,位置 i 对所有元素(值)有一个偏好顺序:它最喜欢最小的元素,其次是第二小的元素,...,最不喜欢最大的元素。即,位置 i 的偏好列表是所有数组元素按照值升序排列。
- 求婚者(元素)的偏好列表:元素希望去到哪个位置?在升序排序中,一个元素
x的理想位置是它在排序后数组中的最终位置(即其排名-1)。但它在算法开始时不知道这个最终排名。然而,我们可以定义一个“目标”顺序:我们希望排序后,元素在数组中的相对顺序与它们的值大小顺序一致。为了构建偏好,我们可以让每个元素x对位置的偏好是按照位置索引升序排列(0,1,2,...)。这反映了一个朴素愿望:每个元素都倾向于占据更靠前的位置。
但是,这样的构造会导致稳定匹配的结果不一定是标准的排序。因为一个较小的元素和一个较大的元素都同样偏好索引 0,接收方(索引 0)更偏好较小的元素,这可能导致稳定匹配正好是升序排序。我们需要更严格的建模。
-
一种巧妙的构造(Deferred Acceptance for Sorting):
将数组arr复制一份,一份视为“男性”(求婚者),另一份视为“女性”(接收方),但两组的成员是相同的元素。每个“男性”元素a对“女性”元素有一个偏好列表:他更偏好比自己小的女性,其次是相等的,最不喜欢比自己大的。但稳定婚姻问题要求偏好是严格且完整的。我们可以定义:
每个元素(作为求婚者)的偏好列表是所有元素(作为接收方)按照值升序排列(值相同时,按原始索引等作为次关键字打破平局)。类似地,每个元素(作为接收方)的偏好列表是所有元素(作为求婚者)按照值升序排列。
运行 Gale-Shapley 算法(男性求婚版本)后,每个男性会匹配到一个女性。如果我们按照男性原始的顺序,将其匹配到的女性的值排列出来,结果会是什么?实际上,Gale-Shapley 男性求婚版本的结果具有一个性质:每个男性得到他可能匹配到的最好的稳定配偶(在所有稳定匹配中,他对这个配偶的偏好是最高的)。在双方偏好列表相同(都是全局升序)的情况下,唯一的稳定匹配是每个元素与自己匹配。这没有产生排序。
-
更实际的“排序”应用:
Gale-Shapley 算法思想在排序中更直接的应用是带有优先级的稳定分配。例如,我们有一个数组,但我们不单纯比较数值大小,而是每个元素还有一个“优先级权重”,我们希望排序的结果在尊重数值顺序的同时,也能尽可能让高优先级的元素靠前,但同时又不能破坏稳定性(即,如果 A 的值小于 B,那么无论优先级如何,A 必须在 B 前面)。这可以建模为一个带有偏序关系的稳定匹配问题,但不是标准的双稳定匹配。
鉴于直接构造一个纯粹的、用 Gale-Shapley 算法实现经典排序(如快速排序、归并排序所做的)并不典型,更常见的思路是将Gale-Shapley 算法的“延迟接受”和“稳定性”概念作为一种启发,用于解决具有双边偏好约束的分配/排序问题。比如,在“招生录取”问题中,学生排序学校,学校排序学生,最终匹配结果是稳定的。这本身可以看作是对“学生-学校”对的一种特殊排序(按稳定性约束排序)。
第二步:算法步骤(以经典 Gale-Shapley 算法为例)
假设我们有两个大小相等的集合:求婚者集合 M 和接收方集合 W。每个成员对另一集合的所有成员有一个严格的偏好排序列表。
-
初始化:
- 所有求婚者标记为“自由”。
- 所有接收方标记为“自由”(没有临时配对)。
-
循环:当存在一个自由的求婚者
m时:
a. 求婚者m向他偏好列表中尚未拒绝过他的最高位接收方w求婚。
b. 如果w是自由的,则m和w临时配对。
c. 如果w已与m'临时配对,则w比较她对m和m'的偏好:
- 如果她更喜欢m,则她与m'解除配对(m'变为自由),并与m临时配对。
- 否则(她更喜欢现任m'),她拒绝m,m保持自由。 -
终止:当没有自由的求婚者时,算法结束。所有临时配对成为最终匹配。
第三步:应用于排序问题的示例
假设我们有一个简单的数组 [3, 1, 2],我们想用稳定婚姻的思路来“排序”。
我们需要构造两个集合。一个想法是:将数组元素作为求婚者,但接收方不是索引位置,而是“排名标签”(Rank Labels)。例如,我们有排名标签 R1(最好)、R2、R3。
- 求婚者(元素)的偏好:每个元素都最想要
R1,然后R2,最后R3。即,所有元素的偏好列表都是[R1, R2, R3]。 - 接收方(排名