代码随想录算法训练营第45天| 139.单词拆分 多重背包

JAVA代码编写

139.单词拆分

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s

**注意:**不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

示例 1:

复制代码
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。

示例 2:

复制代码
输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。
     注意,你可以重复使用字典中的单词。

示例 3:

复制代码
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false

教程:https://programmercarl.com/0139.单词拆分.html

方法一:动态规划

思路:单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。

还是有点反应不过来。

拆分时可以重复使用字典中的单词,说明就是一个完全背包!

步骤

  1. 定义dp i 字符串长度为i的话,dpi为true,表示可以拆分为一个或多个在字典中出现的单词。

  2. 递推公式:

    如果确定dpj 是true,且 j, i 这个区间的子串出现在字典里,那么dpi一定是true。(j < i )。

    所以递推公式是 if(j, i 这个区间的子串出现在字典里 && dpj是true) 那么 dpi = true。

  3. dp数组初始化:dp0 =true,其他初值都是false

  4. 确定遍历顺序:

    如果求组合数就是外层for循环遍历物品,内层for遍历背包

    如果求排列数就是外层for遍历背包,内层for循环遍历物品

    强调物品之间顺序。

    所以说,本题一定是 先遍历背包,再遍历物品。

  5. 举例推导dp数组,

    以输入: s = "leetcode", wordDict = "leet", "code"为例,dp状态如图:

复杂度分析

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( m a x ( m , n ) ) O(max(m, n)) O(max(m,n))
java 复制代码
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        HashSet<String> set = new HashSet<>(wordDict);
        boolean[] valid = new boolean[s.length() + 1];
        valid[0] = true;

        for (int i = 1; i <= s.length(); i++) {
            for (int j = 0; j < i && !valid[i]; j++) {
                if (set.contains(s.substring(j, i)) && valid[j]) {
                    valid[i] = true;
                }
            }
        }

        return valid[s.length()];
    }
}

56. 携带矿石资源(多重背包)

题目描述

你是一名宇航员,即将前往一个遥远的行星。在这个行星上,有许多不同类型的矿石资源,每种矿石都有不同的重要性和价值。你需要选择哪些矿石带回地球,但你的宇航舱有一定的容量限制。

给定一个宇航舱,最大容量为 C。现在有 N 种不同类型的矿石,每种矿石有一个重量 wi,一个价值 vi,以及最多 ki 个可用。不同类型的矿石在地球上的市场价值不同。你需要计算如何在不超过宇航舱容量的情况下,最大化你所能获取的总价值。

输入描述

输入共包括四行,第一行包含两个整数 C 和 N,分别表示宇航舱的容量和矿石的种类数量。

接下来的三行,每行包含 N 个正整数。具体如下:

第二行包含 N 个整数,表示 N 种矿石的重量。

第三行包含 N 个整数,表示 N 种矿石的价格。

第四行包含 N 个整数,表示 N 种矿石的可用数量上限。

输出描述

输出一个整数,代表获取的最大价值。

输入示例
复制代码
10 3
1 3 4
15 20 30
2 3 2
输出示例
复制代码
90
提示信息
复制代码
数据范围:
1 <= C <= 10000;
1 <= N <= 10000;
1 <= w[i], v[i], k[i] <= 10000;

教程:https://programmercarl.com/背包问题理论基础多重背包.html#多重背包

方法一:动态规划

思路多重背包

有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。求解将哪些物品装入背包可使这些物品的耗费的空间总和不超过背包容量,且价值总和最大。

背包最大重量为10。

物品为:

重量 价值 数量
物品0 1 15 2
物品1 3 20 3
物品2 4 30 2

每件物品是有限个!

01背包和多重背包唯一不同就是物品的个数上,我们直接针对遍历顺序经行分析!

需要多加一个循环限制物品的数量

java 复制代码
for (int i = 0; i < n; i++) { // 遍历物品
    for (int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
        // 以上为01背包,然后加一个遍历个数
        for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍历个数
            dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);
        }
    }
}

dp状态图如下:

复杂度分析

  • 时间复杂度: O ( n ∗ b a g W e i g h t 2 ) O(n * bagWeight^2) O(n∗bagWeight2),其中n是物品的数量,bagWeight是背包的容量。
  • 空间复杂度:O(bagWeight),其中bagWeight是背包的容量。
java 复制代码
class Solution {
    public static void main(String[] args) {
        int bagWeight =10;
        int[] weight = new int[] {1,3,4};
        int[] value = new int[] {15,20,30};
        int[] nums = new int[] {2,3,2};
        int n = weight.length;

        int[] dp = new int[bagWeight + 1];

        for (int i = 0; i < n; i++) { // 遍历物品
            for (int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
                // 以上为01背包,然后加一个遍历个数
                for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍历个数
                    dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);
                }
            }
        }
        System.out.println(dp[bagWeight]);
    }
}
相关推荐
QiLinkOS7 小时前
第三视觉理解徐玉生与他的商业活动(30)
大数据·c++·人工智能·算法·开源协议
疯狂打码的少年8 小时前
【操作系统】页面置换算法(OPT/FIFO/LRU)
算法
小O的算法实验室8 小时前
2026年CIE,优化客货协同运输:综合地铁系统的列车容量动态分配
算法
Coder_Shenshen9 小时前
西门子S7CommPlus协议鉴权算法原理与流程详解
网络·后端·算法
硕风和炜10 小时前
【LeetCode: 2492. 两个城市间路径的最小分数 + DFS】
java·算法·leetcode·深度优先·dfs·bfs·并查集
我是一颗柠檬11 小时前
【Java项目技术亮点】加权轮询负载均衡算法
java·算法·负载均衡
灯厂码农11 小时前
C语言动态内存分配完全指南(malloc、calloc、realloc、free)
java·c语言·算法
凯瑟琳.奥古斯特12 小时前
K次取反最大化数组和解法(力扣1005)
开发语言·c++·算法·leetcode·职场和发展
Jerry12 小时前
LeetCode 203. 移除链表元素
算法
地平线开发者13 小时前
征程 6 | 工具链 QAT ObserverBase 源码解析
算法