【LeetCode】Day69-完全平方数&整数拆分&组合总和 Ⅳ

完全平方数

279. 完全平方数【中等】

题解

和昨天的322. 零钱兑换对比一下
在这里插入图片描述
在这里插入图片描述

发现几乎完全一样,只是多了一步计算完全平方数,代码完全可以照搬

class Solution {
    private int[] square;
    public int numSquares(int n) {
        //生成完全平方数数组
        int slen=(int)Math.sqrt(n);
        square=new int[slen];
        judgeSquares(n);
        
        int[] dp=new int[n+1];
        Arrays.fill(dp,n+1);
        dp[0]=0;
        for(int i=1;i<=n;i++){
            for(int j=0;j<slen;j++){
                if(i>=square[j])
                    dp[i]=Math.min(dp[i],dp[i-square[j]]+1);
            }
        }
        return dp[n];
    }
    //筛选出完全平方数
    public void judgeSquares(int n){
        for(int i=0;i<(int)Math.sqrt(n);i++){
            square[i]=(i+1)*(i+1);
        }
    }
}

简化一下代码,发现其实完全平方数数组并不需要,用 j ∗ j ( 0 < j < = n ) j*j (0<j<=\sqrt{n}) jj(0<j<=n ) 就行

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

顺便说一下,乘法比开方的效率高,因此最好用 j*j<i,而不是 j<(int)Math.sqrt(i)

时间复杂度: O ( n n ) O(n\sqrt{n}) O(nn )

空间复杂度: O ( n ) O(n) O(n)

整数拆分

343. 整数拆分【中等】

题解

  1. 状态定义:dp[i] 表示将正整数 i 拆分成至少两个正整数的和之后,这些正整数的最大乘积
  2. 状态转移方程:假设对正整数 i 拆分出的第一个正整数是 j(1≤j<i),即 i 可以拆分成 i 和 i-j,则有以下两种情况
    (1)i-j不拆了:乘积为 j ∗ ( i − j ) j*(i-j) j(ij)
    (2)i-j继续拆:乘积为 j ∗ d p [ i − j ] j*dp[i-j] jdp[ij]
    所以dp[i]=Math.max( i*(i-j) , i*dp[i-j] )
  3. 初始条件:dp[0]=dp[1]=0,因为0和1无法拆分成两个正整数
  4. 返回值:dp[n]
class Solution {
    public int integerBreak(int n) {
        int[] dp=new int[n+1];
        for(int i=2;i<=n;i++){
            for(int j=1;j<i;j++){
                int tmp=Math.max(j*(i-j),j*dp[i-j]);
                dp[i]=Math.max(tmp,dp[i]);
            }
        }
        return dp[n];
    }
}

时间复杂度: O ( n 2 ) O(n^2) O(n2)

空间复杂度: O ( n ) O(n) O(n)

组合总和 Ⅳ

377. 组合总和 Ⅳ【中等】

题解

518. 零钱兑换 II 简直一模一样…不知道说啥了,直接默认代码就得了

class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] dp=new int[target+1];
        dp[0]=1;
        for(int i=1;i<=target;i++){
            for(int j=0;j<nums.length;j++){
                if(i>=nums[j])
                    dp[i]+=dp[i-nums[j]];
            }
        }
        return dp[target];
    }
}

时间复杂度: O ( n 2 ) O(n^2) O(n2)

空间复杂度: O ( n ) O(n) O(n)

总结

题解中有个大佬总结了类似的背包问题的模板,希望用一种规律搞定背包问题,太牛了,非常精辟!学习!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值