给出一个正整数n,寻找最少的完全平方数,是他们的和为n。
(leetcode279)For example, given n = 12
, return 3
because 12 = 4 + 4 + 4
; given n = 13
, return 2
because 13 = 4 + 9
.
思路:以图的思想,每两个数相差一个完全平方数就连接一条边,即求n到0的最短路径;另外,用set标志当前数是否判断过,防止大量的重复计算。用一个队列存储当前步数可到达的数字,依次全部出队计算,再进行下一步数
class Solution {
public int numSquares(int n) {
//以是否相差平方数建立图
// set存放能够到达的数字,防止重复计算
HashSet<Integer> set = new HashSet<Integer>();
// 队列存放当前数字一步能够到达的数字
Queue<Integer> queue = new LinkedList<Integer>();
int step = 0;
queue.offer(n);
while (!queue.isEmpty()) {
int size = queue.size();
step++;
for (int j = 0; j < size; j++) {
int curr = queue.poll();
if (!set.add(curr)) {
continue;
}
for (int i = (int) Math.sqrt(curr); i >= 0; i--) {
// System.out.println(i);
if (curr - i * i == 0) {
return step;
}
queue.offer(curr - i * i);
}
}
}
return n;
}
}
思路2:动态规划。求解n的最优解,即是求n减去可能的平方数x后可以到达的n-x的最优解的最小值
public static int numSquares(int n) {
int[] res = new int[n+1];
for (int i = 0; i < res.length; i++) {
res[i] = Integer.MAX_VALUE;
}
res[0] = 0;
res[1] = 1;
for (int i = 2; i <= n; i++) {
int j = 1;
int min = Integer.MAX_VALUE;
while(i - j*j >= 0) {
min = Math.min(res[i-j*j]+1,min);
++j;
}
res[i] = min;
}
return res[n];
}
。