完全平方数
问题陈述
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...
)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
1 2 3
| 输入: n = 12 输出: 3 解释: 12 = 4 + 4 + 4.
|
常规思路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public int numSquares(int n) { return numSquaresHelper(n, new HashMap<Integer, Integer>()); }
private int numSquaresHelper(int n, HashMap<Integer, Integer> map) { if (map.containsKey(n)) { return map.get(n); } if (n == 0) { return 0; } int count = Integer.MAX_VALUE; for (int i = 1; i * i <= n; i++) { count = Math.min(count, numSquaresHelper(n - i * i, map) + 1); } map.put(n, count); return count; }
|
动态规划
1 2 3 4 5 6 7 8 9 10 11 12 13
| public int numSquares(int n) { int dp[] = new int[n + 1]; Arrays.fill(dp, Integer.MAX_VALUE); dp[0] = 0; for (int i = 1; i <= n; i++) { for (int j = 1; j * j <= i; j++) { dp[i] = Math.min(dp[i], dp[i - j * j] + 1); } } return dp[n]; }
|
BFS
BFS 的话,我们可以一层一层的算。第一层依次减去一个平方数得到第二层,第二层依次减去一个平方数得到第三层。直到某一层出现了 0,此时的层数就是我们要找到平方数和的最小个数。
举个例子,n = 12,每层的话每个节点依次减 1, 4, 9…。如下图,灰色表示当前层重复的节点,不需要处理。

如上图,当出现 0 的时候遍历就可以停止,此时是第 3 层(从 0 计数),所以最终答案就是 3。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public int numSqure(int n){ Queue<Integer> queue=new LinkedList<>(); HashSet<Integer> set=new HashSet<>(); int level=0; queue.add(n); while(!queue.isEmpty()){ int size=queue.size(); level++; for(int i=0;i<size;i++){ int cur=queue.poll(); for(int j=0;j*j<=n;j++){ int next=n-j*j; } if(next==0){ return level; } if(!set.contains(next)){ queue.offer(next); set.add(next); } } } return -1; }
|