Description:
Given a positive integer n, find the least number of perfect square numbers (for example,
1, 4, 9, 16, ...
) which sum to n.
Example 1:
Input: n = 12 Output: 3 Explanation: 12 = 4 + 4 + 4.
Example 2:
Input: n = 13 Output: 2 Explanation: 13 = 4 + 9.
分析:
利用BFS来做,可以将每个整数看成图中的一个节点,如果两个整数之差为一个平方数,那么这两个整数所在的节点就有一条边。
要求解最小的平方数数量,就是求解从节点 n 到节点 0 的最短路径。首先我们可以先求出小于n的平方和序列,不断的在原来n上减去平方和序列并做进一步的判断即可。
代码如下:
public class Solution {
public int numSquares(int n) {
List<Integer> list = getSquares(n);
Queue<Integer> queue = new LinkedList<>();
int[] visited = new int[n+1];
queue.add(n);
visited[n] = 1;
int level = 0;
while (!queue.isEmpty() && !list.isEmpty()){
int size = queue.size();
level++;
while (size-- >0){
int ele = queue.poll();
for (int e : list){
int nextEle = ele - e;
if (nextEle < 0){
break;
}
if (nextEle == 0){
return level;
}
if (visited[nextEle] == 1){
continue;
}
visited[nextEle] = 1;
queue.add(nextEle);
}
}
}
return 1;
}
//获取小于n的平方序列
private static List<Integer> getSquares(int n){
List<Integer> list = new ArrayList<>();
int sq = 1;
int diff = 3;
while (sq <= n){
list.add(sq);
sq += diff;
diff += 2;
}
return list;
}
}
另外该题目也可以利用动态规划完成,思路如下:
若整数数a可以表示为一个任意数x加上一个平方数y*y,也就是a=x + y * y,那么能组成这个数x最少的平方数个数,就是能组成x最少的平方数个数加上1(因为y*y已经是平方数了)。
状态转移方程:dp[x+y*y] = Math.min(dp[x]+1, dp[x+y*y])
代码如下:
class Solution {
public int numSquares(int n) {
int[] dp = new int[n+1];
//初始化数组
Arrays.fill(dp, Integer.MAX_VALUE);
for (int i = 0; i * i <= n; i++){
dp[i*i] = 1;
}
//从小到大找任意数x
for (int x = 0; x <= n; x++){
//小-> 大寻找y*y
for (int y = 0; x + y*y <= n; y++){
dp[x+y*y] = Math.min(dp[x]+1, dp[x+y*y]);
}
}
return dp[n];
}
}