题目:
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
.
思路:
思路1:贪心算法(不适用)。首先考虑贪心算法,即选择小于相应给定值的依次最大平方数之和,如12=9+1+1+1,但是通过题意可知,12的解应为12=4+4+4,可知,贪心算法在此处不适用。
思路2:动态规划+图论
对问题建模:从0到n,每一个数字表示一个节点;如果两份数字x到y相差一个完全平方数,则连接一条边。我们得到一个无权图。此时,原问题转化为,求这个无权图中从n到0的最短路径。
最短路径求解:首先对建立一个step[n+1]的数组,用来存放每一个点到0的最短路径值,初始值为最大路径,即每一次的路径均为1;之后,从小到大,对每一个step[]进行重新赋最小值,保证从0到n中每一个step[]都是最短路径(具体:针对某一点i(1<=i<=n),i到0的下一个位置为所有小于i的i-j*j(1<=j<=?)中路径最短的点,并将每一次得到的最小值赋值给step[i],遍历所有的i-j*j后,step[i]的值就是最短路径)。
程序:
class Solution {
public int numSquares(int n) {
int step[] = new int[n+1];
for( int i = 0; i <= n; i++ )//按最大步骤进行初始化
step[i] = i;
for( int i = 1; i <= n; i++ ){//动态规划,从小到大,每一个点的结果都取最小值
for( int j = 1; i - j*j >= 0; j++)
step[i] = Math.min(step[i-j*j]+1,step[i]);
}
return step[n];
}
}