leetcode
leetcode 2251 ~ 2300
填满背包的最大价格

填满背包的最大价格

难度:

标签:

题目描述

代码结果

运行时间: 205 ms, 内存: 57.4 MB


/*
 * 题目编号:2548
 * 题目:填满背包的最大价格
 * 思路:
 * 1. 这是一个经典的01背包问题。
 * 2. 我们需要一个数组dp,其中dp[i]表示填满容量为i的背包所能获得的最大价格。
 * 3. 对于每个物品,我们有两种选择,放入背包或者不放入背包。
 * 4. 如果不放入背包,则当前dp值不变。
 * 5. 如果放入背包,则更新dp值为dp[i - weight] + value。
 * 6. 最后dp[maxCapacity]就是我们所求的结果。
 * 使用Java Stream来实现主要是利用IntStream来简化循环。
 */
import java.util.stream.IntStream;

public class SolutionStream {
    public int fillBackpack(int maxCapacity, int[] weights, int[] values) {
        int n = weights.length;
        int[] dp = new int[maxCapacity + 1];
        IntStream.range(0, n).forEach(i -> 
            IntStream.iterate(maxCapacity, j -> j >= weights[i], j -> j - 1).forEach(j -> 
                dp[j] = Math.max(dp[j], dp[j - weights[i]] + values[i])
            )
        );
        return dp[maxCapacity];
    }
}

解释

方法:

这个题解采用了贪心算法的思想。首先定义一个辅助函数 sort_key 来计算每个物品的单位质量的价值(价格除以重量),并按照这个价值从高到低进行排序。然后检查所有物品的总重量是否小于背包容量,如果小于则直接返回 -1 表示无法填满背包。接下来遍历排序后的物品列表,优先选择单位价值高的物品加入背包,如果当前物品的重量超过了剩余的背包容量,则按照其单位价值取相应比例的物品填满背包,计算对应的价格,并结束循环。

时间复杂度:

O(n log n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在总重量小于背包容量时直接返回 -1?这是否意味着背包一定要完全填满才算解决问题?
在这个算法中,返回 -1 是因为我们的目标是完全填满背包。如果所有可用的物品的总重量还没有达到背包的容量,那么就无法实现目标,因此直接返回 -1 表示无法解决问题。这里的场景确实是指背包必须被完全填满,这可能是为了满足某些特定的实际需求,如确保物资的最大化利用或其他条件。
🦆
在对物品进行排序时,使用单位价值(价格除以重量)作为排序依据,这种方法在哪些情况下可能不是最优的?
使用单位价值作为排序依据的方法主要是基于贪心算法,它在一些情况下可能不会得到最优解。特别是在物品不能被分割或者每种物品的数量有限的情况下,简单地按单位价值排序并选择可能会导致背包容量用不满,从而无法达到可能的最大总价值。此外,如果问题要求的不仅仅是最大化价值,还包括其他考量(如最小化物品数量或满足特定物品组合的需求),单纯的贪心策略也可能不适用。
🦆
如果在填充过程中遇到连续几个物品的重量都超过剩余容量,如何确保算法还能找到最优解?
在贪心算法的框架下,如果遇到连续几个物品的重量超过剩余容量,算法会尝试按比例取用这些物品的一部分以最大化价值。然而,这种做法仍然依赖于物品可以被分割这一假设。如果物品不可分割,这种情况下贪心算法可能就不再适用,而需要采用动态规划等其他算法来确保找到最优解。动态规划可以考虑多种组合和分割情况,从而在整体上找到价值最大化的解决方案。
🦆
该算法对物品列表进行了排序,是否考虑过在不改变物品原始顺序的情况下解决问题?会有什么不同的考量?
在不改变物品原始顺序的情况下解决问题通常会涉及不同的算法设计,如动态规划。这种方法不依赖于物品的排序,而是通过构建一个决策矩阵来考虑每种可能的物品组合。这样可以在不改变物品顺序的前提下,根据背包的容量逐步决定是否选取当前物品。这种方法在处理不可分割物品或其他复杂约束时更为灵活,但通常会有更高的计算复杂度。

相关问题