You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

技术问询:基于图论判断排列A能否通过指定良好交换对转换为排列B

解决排列交换可行性问题:仅用指定位置对将排列A转换为B

嘿,这个问题本质上是图论中连通分量的典型应用,我来给你一步步拆解清楚怎么判断转换是否可行~

问题明确

先把问题再梳理一遍,确保我们理解一致:

给定两个长度为N的排列A和B,以及一组允许交换的位置对(称为"good pairs"),判断是否可以通过任意次数交换这些位置对中的元素,将排列A转换成排列B。

核心思路

每个允许的交换对,相当于在两个位置之间连了一条无向边。这样所有位置就被划分成了若干个连通分量——在同一个分量里的位置,你可以通过一系列允许的交换,把这些位置上的元素任意置换(因为连通意味着元素可以在分量内部自由移动)。

那判断的关键条件就很清晰了:

对于每个连通分量对应的位置集合,排列A在这些位置上的元素集合,必须和排列B在这些位置上的元素集合完全一致。

换句话说,你只能在连通分量内部调整元素顺序,所以内部的元素必须和目标的元素完全匹配,才能通过交换得到目标排列。

示例验证

用你给出的例子来验证这个思路:

  • N=4,A=[1,3,2,4],B=[1,4,2,3],允许交换的位置对是[[2,4]]
  • 位置的连通分量:{1}, {2,4}, {3}
    • 分量{1}:A和B的元素都是1,匹配
    • 分量{2,4}:A的元素是[3,4],B的元素是[4,3],元素集合完全相同,通过一次交换就能匹配
    • 分量{3}:A和B的元素都是2,匹配
  • 所有分量都满足条件,所以转换可行。

具体实现步骤

我们可以用**并查集(Union-Find/DSU)**来高效管理连通分量,步骤如下:

  1. 初始化并查集,每个位置作为独立节点。
  2. 遍历所有允许的交换对,将对应的位置合并到同一个连通分量中。
  3. 按连通分量分组,分别收集A和B中对应位置的元素。
  4. 检查每个分组的元素集合是否一致,全部一致则返回True,否则返回False。

代码实现(Python)

class DSU:
    def __init__(self, size):
        # 位置是1-based(题目示例里位置用2、4表示),所以数组从1到size
        self.parent = list(range(size + 1))
        self.rank = [0] * (size + 1)
    
    def find(self, x):
        # 路径压缩,加快查询速度
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    
    def union(self, x, y):
        # 按秩合并,保证树的高度尽可能小
        x_root = self.find(x)
        y_root = self.find(y)
        if x_root == y_root:
            return
        if self.rank[x_root] < self.rank[y_root]:
            self.parent[x_root] = y_root
        else:
            self.parent[y_root] = x_root
            if self.rank[x_root] == self.rank[y_root]:
                self.rank[x_root] += 1

def can_transform(A, B, good_pairs, n):
    dsu = DSU(n)
    # 合并所有允许交换的位置对
    for u, v in good_pairs:
        dsu.union(u, v)
    
    # 按连通分量分组收集元素
    group_a = {}
    group_b = {}
    for pos in range(1, n + 1):
        root = dsu.find(pos)
        # 注意A和B是0-based列表,位置是1-based,所以索引要减1
        val_a = A[pos - 1]
        val_b = B[pos - 1]
        
        if root not in group_a:
            group_a[root] = []
            group_b[root] = []
        group_a[root].append(val_a)
        group_b[root].append(val_b)
    
    # 检查每个分组的元素是否匹配(排序后比较,因为排列元素唯一)
    for root in group_a:
        if sorted(group_a[root]) != sorted(group_b[root]):
            return False
    return True

# 测试示例
A = [1, 3, 2, 4]
B = [1, 4, 2, 3]
C = [[2, 4]]
N = 4
print(can_transform(A, B, C, N))  # 输出: True

边界情况补充

  • 如果A和B本身完全相同,不管交换对是什么,都直接返回True
  • 如果交换对为空,每个位置都是独立连通分量,此时必须A和B完全一致才能转换
  • 如果某个连通分量里A的元素集合和B的不匹配(比如A是[2,3],B是[2,4]),那绝对无法转换,因为没法从外部获取缺失的元素

内容的提问来源于stack exchange,提问作者Dikshant Dwivedi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 09:53:12