2024-04-10:用go语言,考虑一个非负整数数组 A,
如果数组中相邻元素之和为完全平方数,我们称这个数组是正方形数组。
现在要计算 A 的正方形排列的数量。
两个排列 A1 和 A2 被认为是不同的,如果存在至少一个索引 i,满足 A1[i] != A2[i]。
输出:2。
答案2024-04-10:
来自左程云。
灵捷3.5
大体过程如下:
1.定义变量和数据结构:
??定义常量MAXN为 13,表示数组的最大长度。
??定义全局变量f,存储阶乘的预计算结果。
2.编写初始化函数init():
??创建长度为MAXN的切片f,并将其第一个元素初始化为 1。
??使用循环计算并预存每个阶乘值。
3.编写函数numSquarefulPerms(nums []int) int来计算正方形排列的数量:
??初始化变量n为数组nums的长度。
??创建二维切片graph和dp,分别用于记录数字之间是否存在完全平方数关系和动态规划的状态。
??遍历数组nums构建图graph,找出数字之间的完全平方数关系。
??初始化变量ans为 0,用于记录正方形排列的数量。
??使用深度优先搜索函数dfs()遍历图graph,并计算正方形排列的数量。
??将数组nums进行排序,以便处理相同数字的情况。
??使用变量start和end遍历排序后的数组nums,计算相同数字之间的排列数量,并更新结果。
??返回最终的正方形排列数量。
4.编写深度优先搜索函数dfs(graph [][]int, i int, s int, n int, dp [][]int) int:
??如果当前状态s表示所有元素都被使用,返回1,表示找到了一种满足条件的排列。
??如果当前状态已经被计算过,直接返回对应的结果。
??初始化变量ans为 0,用于记录满足条件的排列数量。
??遍历与当前位置i相邻的下一个位置next:
??如果下一个位置next还未被包含在当前状态s中,将其加入到状态s中,并递归调用dfs()继续搜索。
??将递归调用的结果累加到变量ans中。
??将结果存储到dp中,并返回。
5.在main()函数中调用numSquarefulPerms(),传入示例数据[1, 17, 8],并打印结果。
总的时间复杂度:O(n * n!)
??预计算阶乘的时间复杂度为 O(MAXN) = O(1),因为 MAXN 是常数。
??构建图和计算正方形排列的数量的时间复杂度为 O(n!),其中 n 是数组nums的长度。
??数组排序的时间复杂度为 O(n * logn),其中 n 是数组nums的长度。
总的空间复杂度:O(n * 2^n)
??动态规划的状态数组dp的空间复杂度为 O(n * 2^n),其中 n 是数组nums的长度。
??构建图的辅助数组graph的空间复杂度为 O(n^2),其中 n 是数组nums的长度。
??其他变量和数据结构的空间复杂度为 O(1)。
Go完整代码如下:
package?main
import?(
"fmt"
"math"
"sort"
)
var?MAXN?int?=?13
var?f?[]int
func?init()?{
f?=?make([]int,?MAXN)
f[0]?=?1
for?i?:=?1;?i?<?MAXN;?i++?{
f[i]?=?i?*?f[i-1]
}
}
func?numSquarefulPerms(nums?[]int)?int?{
n?:=?len(nums)
graph?:=?make([][]int,?n)
dp?:=?make([][]int,?n)
for?i?:=?0;?i?<?n;?i++?{
graph[i]?=?make([]int,?0)
dp[i]?=?make([]int,?1<<n)
for?j?:=?0;?j?<?1<<n;?j++?{
dp[i][j]?=?-1
}
}
for?i?:=?0;?i?<?n;?i++?{
for?j?:=?i?+?1;?j?<?n;?j++?{
s?:=?int(math.Sqrt(float64(nums[i]?+?nums[j])))
if?s*s?==?nums[i]+nums[j]?{
graph[i]?=?append(graph[i],?j)
graph[j]?=?append(graph[j],?i)
}
}
}
ans?:=?0
for?i?:=?0;?i?<?n;?i++?{
ans?+=?dfs(graph,?i,?1<<i,?n,?dp)
}
sort.Ints(nums)
start?:=?0
for?end?:=?1;?end?<?n;?end++?{
if?nums[start]?!=?nums[end]?{
ans?/=?f[end-start]
start?=?end
}
}
ans?/=?f[n-start]
return?ans
}
func?dfs(graph?[][]int,?i?int,?s?int,?n?int,?dp?[][]int)?int?{
if?s?==?(1<<n)-1?{
return?1
}
if?dp[i][s]?!=?-1?{
return?dp[i][s]
}
ans?:=?0
for?_,?next?:=?range?graph[i]?{
if?s&(1<<next)?==?0?{
ans?+=?dfs(graph,?next,?s|(1<<next),?n,?dp)
}
}
dp[i][s]?=?ans
return?ans
}
func?main()?{
nums?:=?[]int{1,?17,?8}
result?:=?numSquarefulPerms(nums)
fmt.Println(result)
}
在这里插入图片描述Python完整代码如下:
#?-*-coding:utf-8-*-
import?math
from?collections?import?defaultdict
MAXN?=?13
f?=?[0]?*?MAXN
def?init():
global?f
f[0]?=?1
for?i?in?range(1,?MAXN):
f[i]?=?i?*?f[i-1]
def?numSquarefulPerms(nums):
n?=?len(nums)
graph?=?defaultdict(list)
dp?=?[[-1?for?_?in?range(1<<n)]?for?_?in?range(n)]
for?i?in?range(n):
for?j?in?range(i?+?1,?n):
s?=?int((nums[i]?+?nums[j])?**?0.5)
if?s?*?s?==?nums[i]?+?nums[j]:
graph[i].append(j)
graph[j].append(i)
def?dfs(i,?s):
if?s?==?(1<<n)?-?1:
return?1
if?dp[i][s]?!=?-1:
return?dp[i][s]
ans?=?0
for?next?in?graph[i]:
if?s?&?(1?<<?next)?==?0:
ans?+=?dfs(next,?s?|?(1?<<?next))
dp[i][s]?=?ans
return?ans
ans?=?0
for?i?in?range(n):
ans?+=?dfs(i,?1?<<?i)
nums.sort()
start?=?0
for?end?in?range(1,?n):
if?nums[start]?!=?nums[end]:
ans?//=?f[end?-?start]
start?=?end
ans?//=?f[n?-?start]
return?ans
init()
nums?=?[1,?17,?8]
result?=?numSquarefulPerms(nums)
print(result)
在这里插入图片描述
领取专属 10元无门槛券
私享最新 技术干货