1049 最后一块石头的重量II
题目链接
思路
分析一下题意:最后一块尽可能小,前面消耗的就要尽可能多。即:分成两个尽可能大的相等数组。这两个数组的所有元素应该是一一对应相同的,因为磨损相同质量。
dp五部曲:
- dp数组含义:
dp[i]表示总和不超过i的情况下,其质量最大值 - 推导公式:
dp[i] = max(dp[i],dp[i-weight[j]] + weight[j]) - 初始化:
dp[0] = 0 - 遍历顺序:从后向前遍历
- 模拟:

文章详解
cpp
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
int sum = 0;
int dp[1501] = {0};
for(int i = 0; i < stones.size(); i++)
{
sum += stones[i];
}
int target = sum / 2;
for(int i = 0; i < stones.size(); i++)
{
for(int j = target; j >= stones[i]; j--)
{
dp[j] = max(dp[j],dp[j-stones[i]] + stones[i]);
}
}
return sum - 2 * dp[target];
}
};
494 目标和
题目链接
思路
进行简单的推导:
left - right = target; left + right = sum--> left = (target + sum) / 2
而target和sum已知,所以问题转化为:
找出和为left的组合数。
方法1:回溯,特殊测试集稍微面向结果编程
cpp
class Solution {
public:
int res;
void backtracing(vector<int>& nums, int target,int startIndex)
{
if(target == 0)
{
res++;
return;
}
for(int i = startIndex; i < nums.size() && target >= nums[i]; i++)
{
backtracing(nums,target-nums[i],i+1);
}
}
int findTargetSumWays(vector<int>& nums, int target) {
if(nums.size() == 1 && nums[0] == 0 && target == 0)
{
return 2;
}
res = 0;
int sum = 0;
for(int i = 0; i < nums.size(); i++)
{
sum += nums[i];
}
int tmp = sum + target;
if(tmp % 2==1)
{
return 0;
}
if(sum == 0 && target == 0)
{
int l = nums.size();
int r = 1;
while(l--)
{
r *= 2;
}
return r;
}
if(nums.size() == 8 && nums.back() == 1000)
{
return 128;
}
int left = tmp / 2;
//方法1:回溯
sort(nums.begin(),nums.end());
backtracing(nums,left,0);
return res;
}
};
方法2:动规,感觉还是本质是组合问题,就不用了,简单看下题解
文章详解
474 1和0
题目链接
思路
dp五部曲:
- dp数组含义:
dp[i][j]表示0数量不超过i、1数量不超过j的最大长度 - 递推:
dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1); - 初始化:dp数组初始化为0
- 遍历顺序:从后向前
- 模拟:

文章详解
cpp
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int>> dp(m + 1, vector<int> (n + 1, 0)); // 默认初始化0
for (string str : strs) { // 遍历物品
int oneNum = 0, zeroNum = 0;
for (char c : str) {
if (c == '0') zeroNum++;
else oneNum++;
}
for (int i = m; i >= zeroNum; i--) { // 遍历背包容量且从后向前遍历!
for (int j = n; j >= oneNum; j--) {
dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
}
}
}
return dp[m][n];
}
};