目录
1.完全平方数

这道题通过动态规划来解决
首先我们设dp[i][j]表示从前i个完全平方数中凑成j所需的最少数量,设置m为sqrt(n),因为对于一个n来说,所需要的完全平方数大小不会超过sqrt(n),比如16,开完为4,最多需要的完全平方数就到4,不可能到5
对于状态转移方程,分为以下两种情况:
- 不选择第i个完全平方数,所以需要从前i - 1个中凑成j,dp[i][j] = dp[i - 1][j]
- 选择第i个,又分为以下情况:
- 选一个i,dp[i][j] = dp[i - 1][j - i * i] + 1
- 选两个i,dp[i][j] = dp[i - 1][j - 2 * (i * i)] + 2
- 最终可以表示为,dp[i][j] = dp[i][j - i * i] + 1
所以dp[i][j] = min(dp[i - 1][j], dp[i][j - i * i] + 1]
初始化的问题,我们需要用到上一个位置和左边的位置,所以需要从上到下,从左到右的初始化,同时注意边界问题,第0行第j列(1 <= j <= n)应当初始化为一个很大的值,表示不可能被选择,因为不会有从0个完全平方数中凑成j的情况
cpp
class Solution {
public:
int numSquares(int n) {
const int INF = 0x3f3f3f3f;
int m = sqrt(n);
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for(int j = 1; j <= n; j++) dp[0][j] = INF;
for(int i = 1; i <= m; i++)
for(int j = 0; j <= n; j++)
{
dp[i][j] = dp[i - 1][j];
if(j >= i * i)
dp[i][j] = min(dp[i][j], dp[i][j - i * i] + 1);
}
return dp[m][n];
}
};
空间优化后
cpp
class Solution {
public:
int numSquares(int n) {
const int INF = 0x3f3f3f3f;
int m = sqrt(n);
vector<int> dp(n + 1, INF);
dp[0] = 0;
for(int i = 1; i <= m; i++)
for(int j = i * i; j <= n; j++)
dp[j] = min(dp[j], dp[j - i * i] + 1);
return dp[n];
}
};