这个题解采用了回溯法来解决问题。首先,为了方便查找每个位置 i 可以放置哪些数字,创建了一个字典 match,其中 match[i] 包含所有可以放在位置 i 的数字(即满足 perm[i] 能被 i 整除或 i 能被 perm[i] 整除的数)。接着,使用 vis 集合来跟踪哪些数字已经在排列中被使用过。backtrack 函数从位置 1 到 n 递归地尝试所有可能的数字,如果构成了一个优美的排列,则增加结果计数器 self.res。
时间复杂度: O(n!)
空间复杂度: O(n^2)
class Solution:
def countArrangement(self, n: int) -> int:
self.res = 0 # 结果计数器
match = defaultdict(list) # 存储每个位置可以放哪些数字
for i in range(1, n+1):
for j in range(1, n+1):
if i%j == 0 or j%i == 0: # 检查是否满足优美排列的条件
match[i].append(j)
vis = set() # 跟踪已使用的数字
def backtrack(index):
if index == n+1: # 若达到排列的尾部
self.res += 1 # 找到一个有效的排列
for x in match[index]: # 尝试每个可以放在当前位置的数字
if x not in vis: # 如果数字还没被使用
vis.add(x) # 标记为已使用
backtrack(index+1) # 递归到下一个位置
vis.discard(x) # 回溯,撤销此次选择
backtrack(1) # 从位置 1 开始回溯
return self.res