给定一个数,找出最少多少个平方数(可以重复)之和为这个数。
分析:
这个题就是一个搜索题,由于是找个数,第一想法就是广度优先搜索。程序正确但是无奈超时。
public class Solution {
public int numSquares(int n) {
//广度优先搜索
int res = 0;
Queue<Integer> q = new LinkedList<>();
q.offer(n);
while(!q.isEmpty()){
int size = q.size();
res++;
for(int i=0; i<size; i++){
int num = q.poll();
for(int k=1; k<=(int)Math.sqrt(n); k++){
if(num - k*k > 0){
q.offer(num - k*k);
}else if(num - k*k == 0){
return res;
}
}
}
}
return res;
}
}
基本上深搜广搜要超时的解决办法就是动态规划。
我们举例子分析问题:1 2 3 4 5 6 7 8 9 10 11 12 13
具体对应的值就不写上来了,但是我们发现比如dp[7] = dp[6] + 1 ,对于12 问题来了:4+4+4 其实就是dp[ 8 ] + 1
所以其实就很简单了: dp的动态联系在于 dp[ j ] = dp[ j - i* i ] +1
其实我觉得理解了深搜广搜本质(搜索树)的,动态规划非常简单,因为思路本质上是一样的。
比如12 我们广搜:
第一层要分成:12-1 12- 4 12 - 9
dp其实一模一样,就是用了一个记录结果的数组正向推起来。
dp[12] 就是 dp[11 ] +1 dp[ 8] +1 dp[3] +1
public class Solution {
public int numSquares(int n) {
int[] dp = new int[n + 1];
for(int i = 1; i <= n; i++) {
int min = Integer.MAX_VALUE;
for(int j = 1; j * j <= i; j++) {
min = Math.min(min, dp[i - j*j] + 1);
}
dp[i] = min;
}
return dp[n];
}
}