0
点赞
收藏
分享

微信扫一扫

初学SpringBoot——请求响应

毅会 2024-03-13 阅读 13
算法

j

算法:

完全平方数就是物品(可以无限件使用),凑个正整数n就是背包,问凑满这个背包最少有多少物品?

动规五部曲:

1.确定dp及其下标

dp[j]:凑成j的最少完全平方数的个数为dp[j]

2.确定递推公式

dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。

此时我们要选择最小的dp[j],

所以递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);

3.dp初始化

dp[0]表示 和为0的完全平方数的最小数量,那么dp[0]一定是0

从递归公式dp[j] = min(dp[j - i * i] + 1, dp[j]);中可以看出每次dp[j]都要选最小的,所以非0下标的dp[j]一定要初始为最大值,这样dp[j]在递推的时候才不会被初始值覆盖

4.确定遍历顺序

本题外层for遍历背包,内层for遍历物品,还是外层for遍历物品,内层for遍历背包,都是可以的!

5.举例推导dp数组

以输入n为5例:

正确代码:

class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n+1];
        for(int i=0;i<=n;i++){
            dp[i] = Integer.MAX_VALUE;
        }
        dp[0] = 0;
        for(int i=1; i*i<=n; i++){
            for (int j=0; j<=n;j++){
                if(j >= i*i){
                dp[j] = Math.min(dp[j-i*i]+1,dp[j]);
                }
                
            }
        }
        return dp[n];

    }
}

注意:

1.for循环中,i的初始值为1,因为题目中说了n最小值为1

2.

 for (int j=0; j<=n;j++){

                if(j >= i*i){

                dp[j] = Math.min(dp[j-i*i]+1,dp[j]);

                }

可以等价替换为

            for (int j=i*i; j<=n;j++){              

                dp[j] = Math.min(dp[j-i*i]+1,dp[j]);                              

            }

这样耗时更短!

最终的耗时短的正确代码:

class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n+1];
        for(int i=0;i<=n;i++){
            dp[i] = Integer.MAX_VALUE;
        }
        dp[0] = 0;
        for(int i=1; i*i<=n; i++){
            for (int j=i*i; j<=n;j++){              
                dp[j] = Math.min(dp[j-i*i]+1,dp[j]);                               
            }
        }
        return dp[n];

    }
}

时间空间复杂度:

  • 时间复杂度: O(n * √n)
  • 空间复杂度: O(n)
举报

相关推荐

0 条评论