Leetcode.279 完全平方数
解法1.动态规划
算法过程:
dp[i]表示i最少可以由几个平方数构成。
1.初试化dp=[0,1,2,⋯,n],长度为n+1,最多次数就是全由1构成。
2.遍历dp,对于i,遍历区间[2,n+1):
遍历所有平方数小于i的数j,遍历区间[1,int(sqrt(i))+1):
dp[i]=min(dp[i],dp[i-j*j]+1)。始终保存所有可能情况中的最小值。
3.返回dp[n]
def numSquares(n):
dp=[i for i in range(n+1)]
for i in range(2,n+1):
for j in range(1,int(i**(0.5))+1):
dp[i]=min(dp[i],dp[i-j*j]+1)
return dp[-1]
复杂度分析:
时间复杂度:O(n*sqrt(n))
空间复杂度:O(n)
解法2. 广度优先遍历(层序遍历)BFS
借助队列实现广度优先遍历(层次遍历)
1.初始化队列queue=[n],访问元组visited={},初试化路径长度step=0
2.特判,若n==0,返回0。
3.循环条件,队列不为空:
step+=1,因为循环一次,意味着一层中的节点已经遍历完,所以路径长度需要加一。
定义当前层中的节点数l=len(queue),遍历当前层的所有节点:
令tmp为队首元素。
遍历所有可能数ii的平方数,遍历区间[1,int(sqrt(tmp))+1):
定义x=tmp-i**2
若==0,返回当前的路径长度。
若x not in visited,表示当前节点未出现过:将该节点入队并在访问数组中加入。
4.返回step
def numSquares(n):
from collections import deque
if n == 0: return 0
queue = deque([n])
step = 0
visited = set()
while(queue):
step+=1
l=len(queue)
for _ in range(l):
tmp=queue.pop()
for i in range(1,int(tmp**0.5)+1):
x=tmp-i**2
if(x==0):
return step
if(x not in visited):
queue.appendleft(x)
visited.add(x)
return step
解法3.数学方法,拉格朗日四平方和定理:说明每个正整数均可表示为4个整数的平方和。
def numSquares3(n):
while n % 4 == 0:
n/=4
if n % 8 == 0:
return 4
a = 0
while a**2 <= n:
b = int((n - a**2)**0.5)
if a**2 + b**2 == n:
return bool(a) + bool(b)
a += 1
return 3