难度困难30
给定一个非负整数数组 A
,如果该数组每对相邻元素之和是一个完全平方数,则称这一数组为正方形数组。
返回 A 的正方形排列的数目。两个排列 A1
和 A2
不同的充要条件是存在某个索引 i
,使得 A1[i] != A2[i]。
示例 1:
输入:[1,17,8] 输出:2 解释: [1,8,17] 和 [17,8,1] 都是有效的排列。
示例 2:
输入:[2,2,2] 输出:1
提示:
1 <= A.length <= 12
0 <= A[i] <= 1e9
class Solution:
def numSquarefulPerms(self, A: List[int]) -> int:
self.res = 0
num = len(A)
if num == 0:
return 0
elif num == 1:
return 1 if math.sqrt(A[0]) % 1 == 0 else 0
# 给数组A从小到大排序
A.sort()
Visited = [False for _ in A]
def _judge(a : int, b : int) -> bool:
return True if math.sqrt(a + b) % 1 == 0 else False
def _trace_back(depth : int, path : List[int], Visited : List[bool]):
# 剪枝
if depth > 1 and not _judge(path[-1], path[-2]):
return
# 递归出口返回结果
if depth == num:
self.res += 1
return
for i in range(num):
if not Visited[i]:
if i > 0 and A[i] == A[i - 1] and not Visited[i - 1]:
continue
Visited[i] = True
path.append(A[i])
_trace_back(depth + 1,path,Visited)
path.pop()
Visited[i] = False
_trace_back(0,[],Visited)
return self.res
心得体会
1.这是一道经典的回溯问题,不同于模板,本题依据具体的题意加入了剪枝的判断条件。当当前路径列表内倒数第一项与倒数第二项相加和不是平方数时直接返回停止迭代。
2.回溯问题要注意的一点就是剪枝条件要放在递归出口前面!!!!!
3.python的函数传递只要形参是列表,字典,tuple等可以改变的容器都是引用传值!!!