152、【动态规划】leetcode ——416. 分割等和子集:滚动数组+二维数组(C++版本)
2023-09-11 14:20:01 时间
题目描述
原题链接:416. 分割等和子集
解题思路
题目要求是划分出两个相等的集合,那么这两个相等的集合相加,一定等于偶数并且为总集合的二分之一,若总集合求和后不为偶数,则一定不可以划分,直接返回false
即可。
因为本题的每个数只能用一次,本题可转化为01背包问题,背包容量为原集合求和的二分之一,选择nums
中的数,进行装取,当装入的容量达到求和的二分之一时,说明可以划分集合。其中,原集合中的数=物品体积=物品价值,找到某种装入方式价值最大,也就是找到某种方式,在确定体积下装入最多。
动态规划五步曲:
(1)dp[j]的含义: 在背包体积j的条件下,可装入的物品体积最大之和。
(2)递推公式: dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
(3)dp数组初始化: dp[0] = 0
(4)遍历顺序: 因采用滚动数组,因此先物品,再背包,内层按背包容量从大到小的顺序遍历。
(5)举例:
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sumNums = 0;
for(int i = 0; i < nums.size(); i++) sumNums += nums[i];
if(sumNums % 2 != 0) return false;
sumNums /= 2;
int dp[10001] = {0};
int n = nums.size();
for(int i = 0; i < n; i++) {
for(int j = sumNums; j >= nums[i]; j--) {
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
}
}
return dp[sumNums] == sumNums;
}
};
二维数组
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sumNums = 0;
for(int i = 0; i < nums.size(); i++) sumNums += nums[i];
if(sumNums % 2 != 0) return false;
sumNums /= 2;
int n = nums.size();
vector<vector<int>> dp(n + 1, vector<int>(sumNums + 1));
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= sumNums; j++) {
if(nums[i - 1] > j)
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - nums[i - 1]] + nums[i - 1]);
}
}
return dp[n][sumNums] == sumNums;
}
};
参考文章:416. 分割等和子集
相关文章
- C++ 结构体
- leetcode Valid Palindrome C++&python 题解
- C++ 类的静态成员及静态成员函数
- 201、【数组】leetcode ——面试题 17.05. 字母与数字(C++版本)
- 189、【动态规划】leetcode ——312. 戳气球(C++版本)
- 188、【栈与队列】leetcode ——84. 柱状图中最大的矩形:暴力解法+单调栈(C++/Python版本)
- 186、【栈与队列】leetcode ——503. 下一个更大元素 II(C++版本)
- 179、【动态规划】leetcode ——115. 不同的子序列(C++版本)
- 173、【动态规划】leetcode ——300. 最长递增子序列 (C++版本)
- 171、【动态规划】leetcode ——309. 最佳买卖股票时机含冷冻期 (C++版本)
- 168、【动态规划】leetcode ——121. 买卖股票的最佳时机:dp数组+变量优化 (C++版本)
- 164、【动态规划】leetcode ——213. 打家劫舍 II:环形列表线性化(C++版本)
- 157、【动态规划】leetcode ——377. 组合总和 Ⅳ:二维数组+一维滚动数组(C++版本)
- 158、【动态规划】leetcode ——518. 零钱兑换 II:二维数组+一维滚动数组(C++版本)
- 155、【动态规划】leetcode ——474. 一和零:三维数组+二维滚动数组(C++版本)
- 149、【动态规划】leetcode ——343. 整数拆分(C++版本)
- 146、【动态规划】leetcode ——746. 使用最小花费爬楼梯:递归法+迭代法(C++版本)
- 145、【动态规划】leetcode ——70. 爬楼梯:暴力法+动态规划(C++版本)
- 144、【动态规划】leetcode ——509. 斐波那契数:递归法+迭代法(C++版本)
- 141、【贪心算法】leetcode ——56. 合并区间(区间重叠解法+双指针解法)(C++版本)
- 140、【贪心算法】leetcode ——763. 划分字母区间(区间边界更新)(C++版本)
- 136、【贪心算法】leetcode ——860. 柠檬水找零(贪心策略)(C++版本)
- 133、【贪心算法】leetcode ——1005. K 次取反后最大化的数组和(模拟变化+贪心策略)(C++版本)
- 124、【回溯算法】leetcode ——46. 全排列(C++版本)
- 93、【树与二叉树】leetcode ——222. 完全二叉树的节点个数:普通二叉树求法+完全二叉树性质求法(C++版本)
- 68、【哈希表】leetcode——349. 两个数组的交集(C++版本)
- 60、【数组】leetcode——904. 水果成篮-滑动窗口:最大窗口(C++版本)
- C++模板实战6:迭代器
- 在CC++中char 、short 、int各占多少个字节
- C/C++教程 第二十七章 —— 脚本开发