一、问题描述
pSort问题描述如下:在一个大小为 nn 的数组中,每个单元格包含一个初始编号(从 1 到 nn),以及一个喜爱编号。在一次操作中,第 ii 个单元格可以与其他单元格交换其值,条件是两者的喜爱编号满足 ∣i−j∣=di|i - j| = d_i。这里 did_i 是第 ii 个单元格的喜爱编号。
我们需要判断能否通过一系列操作,将数组的状态调整为给定的目标状态。
输入:
- 第一行包含整数 nn((1 \leq n \leq 100\)),表示数组的大小。
- 第二行是一个从 1 到 nn 的排列,表示目标状态。
- 第三行是喜爱编号数组,包含 nn 个整数。
输出: 如果可以通过合法操作达到目标状态,输出 YES
;否则输出 NO
。
二、示例解析
示例 1
输入:
5
5 4 3 2 1
1 1 1 1 1
输出:
YES
解析:喜爱编号为 1,意味着每个单元格可以与相邻的单元格交换值。通过若干次交换可以逆转整个数组,满足目标状态。
示例 2
输入:
7
4 3 5 1 2 7 6
4 6 6 6 1 1 1
输出:
NO
解析:一些单元格受喜爱编号的限制,无法与目标状态对齐。
三、解决方案:DFS实现
为了判断是否可以通过交换操作将数组调整到目标状态,我们可以将问题建模为图的连通性问题:
- 每个单元格视为一个节点。
- 如果两个节点满足交换条件,则在它们之间建立一条边。
- 利用深度优先搜索(DFS),找到每个连通分量,判断目标状态是否符合当前分组。
四、Python代码实现
以下是完整的 Python 实现代码:
def dfs(node, graph, visited, group, root):
"""
深度优先搜索,将同一连通分量的节点分为一组
:param node: 当前节点
:param graph: 邻接表表示的图
:param visited: 是否访问过
:param group: 节点组编号
:param root: 当前连通分量的根节点
"""
if visited[node]:
return
visited[node] = True
group[node] = root
for neighbor in graph[node]:
if not visited[neighbor]:
dfs(neighbor, graph, visited, group, root)
def main():
# 输入处理
n = int(input()) # 数组大小
target = [0] + list(map(int, input().split())) # 目标状态
favorite = [0] + list(map(int, input().split())) # 喜爱编号
# 构建图
graph = [[] for _ in range(n + 1)]
for i in range(1, n + 1):
d = favorite[i]
if i - d > 0: # 左边邻居
graph[i].append(i - d)
graph[i - d].append(i)
if i + d <= n: # 右边邻居
graph[i].append(i + d)
graph[i + d].append(i)
# 连通分量标记
visited = [False] * (n + 1)
group = [0] * (n + 1)
for i in range(1, n + 1):
if not visited[i]:
dfs(i, graph, visited, group, i)
# 验证目标状态是否可达
possible = True
for i in range(1, n + 1):
if group[i] != group[target[i]]:
possible = False
break
print("YES" if possible else "NO")
if __name__ == "__main__":
main()
五、代码详解
1. 图的构建
我们通过一个邻接表 graph
构建图。对于每个单元格 ii:
- 如果 i−dii - d_i 在数组范围内,则在 ii 和 i−dii - d_i 之间建立边。
- 如果 i+dii + d_i 在数组范围内,则在 ii 和 i+dii + d_i 之间建立边。
2. 深度优先搜索(DFS)
DFS 用于遍历图的连通分量。每个连通分量分配一个组编号(group
),便于后续判断目标状态的可行性。
3. 验证目标状态
对于每个单元格,如果其组编号与目标状态中对应位置的组编号不同,则说明目标状态不可达。
六、复杂度分析
- 时间复杂度:
- 图的构建需要 O(n)O(n) 时间。
- DFS 遍历每个节点和边,时间复杂度为 O(n+m)O(n + m),其中 mm 是边的数量。由于 m≤2nm \leq 2n,总复杂度约为 O(n)O(n)。
- 空间复杂度:
- 图的邻接表占用 O(n)O(n) 空间。
- 其他辅助数组如
visited
和group
也需要 O(n)O(n) 空间。
总的来说,时间和空间复杂度均为 O(n)O(n)。
七、测试用例
测试用例 1:
输入:
5
5 4 3 2 1
1 1 1 1 1
输出:
YES
测试用例 2:
输入:
7
4 3 5 1 2 7 6
4 6 6 6 1 1 1
输出:
NO
测试用例 3:
输入:
7
4 3 5 2 1 7 6
4 6 6 6 1 1 1
输出:
YES
八、总结
通过将问题建模为图的连通性问题,我们利用 DFS 有效地解决了 pSort 问题。该解决方案不仅直观易懂,而且在处理 nn 较大的情况下依然高效。
如果本文对你有所帮助,记得点赞和收藏!欢迎在评论区分享你的优化思路或其他解决方法!