当前位置: 首页 > article >正文

算法训练(leetcode)二刷第三十天 | *46. 携带研究材料(第六期模拟笔试)、416. 分割等和子集

刷题记录

  • *46. 携带研究材料(第六期模拟笔试)
    • 二维数组
    • 滚动数组
  • 416. 分割等和子集

*46. 携带研究材料(第六期模拟笔试)

卡码网题目地址

二维数组

01背包问题。用二维数组进行动态规划。

dp[i][j]:访问到第i个物品,在背包容量为j时的最大价值。
初始化:第一个物品在背包容量大于等于其所占空间时的价值为该物品价值。
递推公式:dp[i][j] = max(dp[i-1][j], dp[i][j-cost[i]]+values[i])

其中,

dp[i-1][j]代表上一个物品在容量为j时的最大价值,也就是不把下标为i的物品放入背包;

dp[i][j-cost[i]]+values[i]代表将当前下标为i的物品放入背包,dp[i][j-cost[i]]是获取当背包剩余空间刚好放下当前物品时的最大价值,可以理解为背包腾出当前背包占用空间的大小。

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

// java
import java.util.Scanner;

public class Main{
    
    
    
    public static void main(String[] args){
        int m,n;
        Scanner sc = new Scanner(System.in);
        m = sc.nextInt();
        n = sc.nextInt();
        
        // Bag[] bag = new bag[m];
        
        int[] cost = new int[m];
        for(int i=0; i<m; i++) {
            cost[i] = sc.nextInt();
        }
        
        int[] values = new int[m];
        for(int i=0; i<m; i++) {
            values[i] = sc.nextInt();
        }
        
        int[][] dp = new int [m][n+1];
        
        for(int j=cost[0]; j<=n; j++){
            dp[0][j] = values[0];
        }
        
        for(int i=1; i<m; i++){
            for(int j=0; j<=n; j++){
                if(j<cost[i]) {
                    // 当前容量装不下
                    dp[i][j] = dp[i-1][j];
                }else{
                    // 当前容量能装下
                    dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-cost[i]]+values[i]);
                    
                }
            }
        }
        System.out.println(dp[m-1][n]);
    }
}

滚动数组

这里需要主要在遍历背包容量时是倒序。

因为正序遍历容量会导致一个物品被放入多次:
dp[1] = dp[1 - weight[0]] + value[0] = 15

dp[2] = dp[2 - weight[0]] + value[0] = 30

逆序只放一次:
dp[2] = dp[2 - weight[0]] + value[0] = 15 (dp数组已经都初始化为0)

dp[1] = dp[1 - weight[0]] + value[0] = 15

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

// java
import java.util.Scanner;

public class Main{
    
    
    
    public static void main(String[] args){
        int m,n;
        Scanner sc = new Scanner(System.in);
        m = sc.nextInt();
        n = sc.nextInt();
        
        int[] cost = new int[m];
        for(int i=0; i<m; i++) {
            cost[i] = sc.nextInt();
        }
        
        int[] values = new int[m];
        for(int i=0; i<m; i++) {
            values[i] = sc.nextInt();
        }
        
        
        int[] dp = new int [n+1];
        
        for(int i=0; i<m; i++){
            for(int j=n; j>=cost[i]; j--){
                dp[j] = Math.max(dp[j], dp[j-cost[i]] + values[i]);
            }
        }
        System.out.println(dp[n]);
        
    }
}

416. 分割等和子集

leetcode题目地址

回溯法超时。仍然采用01背包的解题思路。先对数组中的所有元素求和,若元素和无法整除2直接返回false。

dp[j]记录中值为j时的最大的元素和。若dp[j]==j则可以拆分为两个和为j的子集。

使用滚动数组依旧是从后向前遍历。

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

// java
class Solution {
    
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for(int i=0; i<nums.length; i++){
            sum += nums[i];
        }
        if(sum % 2 != 0) return false;
        int mid = sum/2;
        
        
        int[] dp = new int[mid+1];
        for(int i=0; i<nums.length; i++){
            for(int j=mid; j>=nums[i]; j--){
                dp[j] = Math.max(dp[j], dp[j-nums[i]]+nums[i]);
            }
        }
        return dp[mid] == mid;
    }
}

http://www.kler.cn/a/409295.html

相关文章:

  • 安宝特方案 | AR助力紧急救援,科技守卫生命每一刻!
  • 【漏洞复现】广州锦铭泰软件 F22服装管理软件系统 Load.ashx 任意文件读取漏洞
  • 图论最短路(floyed+ford)
  • 微信小程序包之加农炮游戏
  • 【Bluedroid】A2DP SINK播放流程源码分析
  • 分布式 Data Warebase - 构筑 AI 时代数据基石
  • C# 数据结构之【图】C#图
  • D74【 python 接口自动化学习】- python 基础之HTTP
  • 【Android】View的解析—滑动篇
  • 手机发展史介绍
  • 2024年11月最新 Alfred 5 Powerpack (MACOS)下载
  • 在ubuntu中查看csv
  • Windows RDP连接Ubuntu桌面
  • Spring 框架七大模块(Java EE 学习笔记03)
  • SpringMVC接收请求参数
  • Python学习——字符串操作方法
  • Unity Shader常见函数 内置Built-in/URP等效函数
  • 【WPF】Prism学习(九)
  • android-sdk 安装脚本
  • BERT的基本理念
  • Github工作流
  • 高级网络安全——移动IP (GSM认证和密钥协议)(week6)
  • Win11下载和配置VSCode(详细讲解)
  • ant vue3 form嵌套校验
  • C++ 优先算法 —— 长度最小的子数组(滑动窗口)
  • SD NAND 的 SDIO在STM32上的应用详解