算法思想一:动态规划
解题思路:
将问题转换为01背包问题,两个分组的值越接近总和一半差值越小,将总和一半看作背包的最大容量,每次放入的数字就是每次的体积,最后做差返回即可
定义dp数组,其中表示背包空间为 i 时装物品的最大价值:
- :背包容量 j 装不下第个礼物装不下,继承的值
- 背包容量 j 装得下第个物品在装下与装不下中选择最大值
图解:
代码展示:
Python版本
class Solution: def maxPresent(self , presentVec ): # write code here # 数组总和 s = sum(presentVec) # 计算最多选礼物数量 bv = s//2 + 1 # dp数组 dp = [0]*bv # 遍历 for i in range(len(presentVec)): for j in range(bv-1, presentVec[i]-1, -1): # 动态转移方程 dp[j] = max(dp[j], dp[j-presentVec[i]] + presentVec[i]) return s - 2 * dp[bv-1]
复杂度分析
时间复杂度:N表示数组的长度,第一次遍历时间,第二次遍历时间,求和计算时间,最后为
空间复杂度:dp数组占用空间
算法思想二:递归
解题思路:
对于方法一,可以用递归的思想进行解决。对于第 i 个礼物,背包容量剩下为 capacity,如果装不下,则子问题是。如果装得下,则子问题为。
据上述描述进行递归计算,即可得到本题的答案。
代码展示:
C++版本
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param presentVec int整型vector 每个礼物的价值 * @return int整型 */ int maxPresent(vector<int>& presentVec) { // write code here if(presentVec.size() == 1) // 只有一个的情况 return presentVec[0]; int mysum = 0; // 声明求和 // 计算总价值 for(int i = 0; i < presentVec.size(); i++) mysum += presentVec[i]; int n = mysum / 2; // dp数组 vector<vector<int> > dp(n + 1, vector<int>(n + 1, -1)); int max = recursion(presentVec.size(), n, presentVec, dp); // 更新max用于计算最终答案 return abs(mysum - 2 * max); } // 递归函数 int recursion(int n, int capacity, vector<int>& presentVec, vector<vector<int>>& dp) { // 特殊情况 if (n <= 0 || capacity == 0) { dp[n][capacity] = 0; // 初始条件 return 0; } else if(presentVec[n - 1] > capacity) { if(dp[n - 1][capacity] == -1) // 装不下 dp[n - 1][capacity] = recursion(n - 1, capacity, presentVec, dp); return dp[n - 1][capacity]; // 返回局部值 } else { //可以装下的情况 if(dp[n - 1][capacity] == -1) dp[n - 1][capacity] = recursion(n - 1, capacity, presentVec, dp); if(dp[n - 1][capacity - presentVec[n - 1]] == -1) dp[n - 1][capacity - presentVec[n - 1]] = recursion(n - 1, capacity - presentVec[n - 1], presentVec, dp); dp[n][capacity] = max(dp[n - 1][capacity], dp[n - 1][capacity - presentVec[n - 1]] + presentVec[n - 1]); // 返回子问题结果 return dp[n][capacity]; } return 0; } };
复杂度分析
时间复杂度:N表示数组的长度,最差情况下递归遍历整个dp数组时间
空间复杂度:dp数组占用空间