Given a positive integer n, find the least number of perfect square numbers (for example, 1,
4, 9, 16, ...
) which sum to n.
For example, given n = 12
, return 3
because 12
= 4 + 4 + 4
; given n = 13
, return 2
because 13
= 4 + 9
.
一开始用的递归,dfs加hash判重,一个数的最小步数可以看做比这个数小的完全平方数的步数+(所求数-选定的完全平方数)步数。
递归还是慢了点,可以递归应该也可以dp,改成dp版本就ok了。
递推方程dp(n)=dp(i)+dp(n-i),其中i是比n小的完全平方数。
递归+hash版本(大量重复搜索,虽有判重,函数调用次数仍然是指数级,较慢)
HashMap<Integer, Integer> hashmap;
public int numSquares(int n)
{
hashmap=new HashMap<>(n);
return dp(n);
}
public int dp(int n)
{
if(hashmap.containsKey(n))
return hashmap.get(n);
double sqrt=Math.sqrt(n);
if(Math.ceil(sqrt)==sqrt)
{
hashmap.put(n, 1);
return 1;
}
int min=Integer.MAX_VALUE;
for(int i=(int) sqrt;i>=1;i--)
{
int square=i*i;
int sum=dp(square)+dp(n-square);
min=Math.min(min, sum);
}
hashmap.put(n, min);
return min;
}
DP版本
public static int numSquares(int n)
{
int sqrt=(int) Math.sqrt(n);
int[] dp=new int[n+1];
for(int i=1;i<=sqrt;i++)
dp[i*i]=1;
for(int i=1;i<=n;i++)
{
int min=Integer.MAX_VALUE;
int sq=(int) Math.sqrt(i);
for(int j=sq;j>=1;j--)
{
int square=j*j;
min=Math.min(min, dp[square]+dp[i-square]);
}
dp[i]=min;
}
return dp[n];
}