LeetCode:84.完全平方数
目录
1.完全平方数
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的情况
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];}
};
空间优化后
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];}
};