【每日刷题】代码随想录-动规14、18、23、24、LC-动规118

1. 代码随想录-动规14.LC1049.最后一块石头的重量II

题目链接
最小重量,即最小的相差重量。
石头总重/2,用01背包。
本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,这样就化解成01背包问题了。因为石头总重/2是向下取整,所以剩下的重量为sum-target*2

代码

class Solution {
    public int lastStoneWeightII(int[] stones) {
        int sum = 0;
        for (int i=0; i<stones.length; i++){
            sum += stones[i];
        }
        int target = sum/2;
        int[] dp = new int[target+1];
        for (int i=0; i<stones.length; i++){
            for (int j=target; j>=stones[i]; j--){
                dp[j] = Math.max(dp[j], dp[j-stones[i]]+stones[i]);
            }
        }
        return (sum-dp[target]*2);
    }
}

2. 代码随想录-动规18.完全背包

完全背包和01背包区别就是:完全背包可以重复多次,01背包一个物品只能放一次。

总结下:
01背包二维
遍历顺序:先背包或者先物品都可以。
先物品,再背包:从1开始遍历,判断j<weight[i]条件
初始化:i=0和j=0

01背包一维:
遍历顺序:物品从0开始遍历,背包从最大递减到weight[i]遍历(为了保证物品只能放一次)。且必须先物品再背包(因为遍历公式依赖左上角,必须左上角先有值)。
初始化:dp[0]=0;背包容量为0,最大价值为0。

完全背包:
遍历顺序:物品从0开始遍历,背包从小递增遍历(保证物品可重复多次)。此时先物品再背包或先背包再物品都可。先物品再背包的话j从=weight[i]开始遍历。
初始化:dp[0]=0;背包容量为0,最大价值为0。

import java.util.*;
public class Main{
    public static void main (String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int V = sc.nextInt();
        int[] weight = new int[N];
        int[] value = new int[N];
        int flag = 0;
        for (int i=0; i<N; i++){
            for (int j=0; j<2; j++){
                if (flag == 0){
                    weight[i] = sc.nextInt();
                    flag = 1;
                }else{
                    value[i] = sc.nextInt();
                    flag = 0;
                }
            }
        }
        int[] dp = new int[V+1];
        for (int i=0; i<N; i++){
            for (int j=weight[i]; j<V+1; j++){
                dp[j] = Math.max(dp[j], dp[j-weight[i]]+value[i]);
            }
        }
        System.out.println(dp[V]);
        sc.close();
    }
}

3. LC动规118.杨辉三角

题目链接
思路:
dp数组:dp[i][j] = dp[i-1][j-1]+dp[i-1][j];
10000
11000
12100
13310
14641
也可直接用list,row.add(ret.get(i - 1).get(j - 1) + ret.get(i - 1).get(j));,用从list里取元素的方法。

代码:

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> list = new ArrayList<>();
        int[][] dp = new int[numRows][numRows];
        for (int temp=0; temp<numRows; temp++){
            dp[temp][0] = 1;
        }
        for (int i=1; i<numRows; i++){
            for (int j=1; j<numRows; j++){
                dp[i][j] = dp[i-1][j-1]+dp[i-1][j];
            }
        }
        for (int i=0; i<numRows; i++){
            List<Integer> temp = new ArrayList<>();
            for (int j=0; j<numRows; j++){
                if (dp[i][j] != 0){
                    temp.add(dp[i][j]);
                }else{
                    break;
                }
            }
            list.add(new ArrayList<>(temp));
        }
        return list;
    }
}

4. LC322.零钱兑换

题目链接
代码

// 动规完全背包
class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount+1];
        dp[0] = 0;
        for (int temp=1; temp<amount+1; temp++){
            dp[temp] = Integer.MAX_VALUE;
        }
        for (int i=0; i<coins.length; i++){
            for (int j=coins[i]; j<amount+1; j++){
                if (dp[j-coins[i]] != Integer.MAX_VALUE){
                    dp[j] = Math.min(dp[j],dp[j-coins[i]]+1);
                }
            }
        }
        if (dp[amount] != Integer.MAX_VALUE){
            return dp[amount];
        }else{
            return -1;
        }
    }
}

动规完全背包。注意这里是Min
所以初始化为了不让初始化的值覆盖应得到的值,dp[0] = 0,其余初始化为Integer.MAX_VALUE;

易错注意:
for循环里加了条件if (dp[j-coins[i]] != Integer.MAX_VALUE)
最后结尾也要考虑(dp[j-coins[i]] = Integer.MAX_VALUE)的情况

5. LC279.完全平方数

题目链接
代码

//动规完全背包
class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n+1];
        int num = (int)Math.sqrt(n);
        for (int temp=0; temp<dp.length; temp++){
            dp[temp] = Integer.MAX_VALUE;
        }
        dp[0] = 0;
        dp[1] = 1;
        for (int i=1; i<=num; i++){
            for (int j=i*i; j<=n; j++){
                dp[j] = Math.min(dp[j], dp[j-i*i]+1);
            }
        }
        return dp[n];
    }
}

dp[j],和为j的完全平方数的最少数量。
1,4,9…是物品。
没从0开始是因为题目是从1开始

不需要像上题的if statement,因爲在完全平方數這一題不會有"湊不成"的狀況發生( 一定可以用"1"來組成任何一個n),故comment掉這個if statement。

  • 25
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值