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.
解此题要先了解四平方数和定理,即每个正整数均可表为四个整数的平方和。
解题思路:对于完美平方数构成的最小数量问题,首先考虑能否用动态规划解题,查分n查看是否能够构造最优子问题的解和找出重叠子问题。通过分析可以使用dp[n],表示n的完美平方数最小构成数量,可以使用两个for循环,第一个i从3到n,第二个从j=1到j*j<=i,然后构造出状态转移方程dp[i] = min(dp[i], dp[i - j*j] + 1);代码如下:
class Solution {
public:
int numSquares(int n)
{
if(n <= 3)
return n;
vector<int> rest;
for(int i = 0; i <= n; i++)
{
rest.push_back(i);
}
for(int i = 3; i <= n ; i++)
{
for(int j = 1; j*j <= i ; j++)
{
rest[i] = min(rest[i], rest[i - j*j] + 1);
}
}
return rest[n];
}
};
Leetcode-279Perfect Squares(完美广场)
[LeetCode] 279. Perfect Squares 完全平方数
此题也可以通过BFS解决:
解题思路二:将问题解转化为图论
引入vis标记,已加入的数字就不再加入队列计算,发现第一个结果为0的,就直接返回,因为他是最短的。引入vis,是避免多余的计算,因为vis=1代表之前已经算过了,如果重复计算,路径长度只会比之前的长,所以直接已经计算过的数字直接跳过。代码如下:
class NodeItem
{
public:
int num;
int step;
NodeItem(int n, int s):num(n),step(s){}
};
class Solution {
public:
int numSquares(int n)
{
if(n <= 3)
return n;
vector<int> vis(n+1, 0);
queue<NodeItem*> qu;
qu.push(new NodeItem(n, 0));
while(!qu.empty())
{
NodeItem *pItem = qu.front();
qu.pop();
int num = pItem->num;
for(int i = 1 ; i*i <= num; i++)
{
int val = num - i*i;
if(val == 0)
{
return pItem->step + 1;
}
else if(val < 0)
{
break;
}
else
{
if(vis[val] == 0)
{
vis[val] = 1;
qu.push(new NodeItem(val, pItem->step + 1));
}
}
}
}
return n;
}
};