代码随想录算法训练营 | 1049. 最后一块石头的重量 II,494. 目标和,474.一和零
1049. 最后一块石头的重量 II
题目链接:1049. 最后一块石头的重量 II
文档讲解︰代码随想录(programmercarl.com)
视频讲解︰最后一块石头的重量 II
日期:2024-10-10
想法:这这么会是分割等和子集一类的问题。。。
Java代码如下:
class Solution {
public int lastStoneWeightII(int[] stones) {
if(stones == null || stones.length == 0) return 0;
int sum = 0;
for(int num : stones) {
sum += num;
}
int target = sum / 2;
int[] dp = new int[target + 1];
for(int i = 0; i < stones.length; i++) {
for(int j = target; j >= stones[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
}
}
return sum - 2 * dp[target];
}
}
494. 目标和
题目链接:494. 目标和
文档讲解︰代码随想录(programmercarl.com)
视频讲解︰目标和
日期:2024-10-10
想法:假设加法的总和为bagSize,那么减法对应的总和就是sum - bagSize,所以要求的是 bagSize - (sum - bagSize) = target; bagSize = (target + sum) / 2
此时问题就转化为,用nums装满容量为bagSize的背包,有几种方法。
- dp的意思是有多少种组合满足,二维数组dp[i][j]表示nums种0到i的数相加得到j的组合数为dp[i][j],
- 递推公式:第一种情况dp[i - 1][j]表示不加上nums[i]这个数时能得到和为j的组合数,第二种情况要加上nums[i],先就得腾出j - nums[i]的空间,看此时dp[i - 1][j - nums[i]]有多少组合,这个组合数就是加上nums[i]总和为j的组合数。
3.初始化:初始化第一行第一列,第一行j刚好等于nums[0]时会有1种(要nums[0]),第一列的话如果nums[0]不是0,那么就1种组合法(不要nums[0]),如果nums[0]是0的话就会麻烦点,那么就2^1 = 2种组合法(不要nums[0],要nums[0]都行),第一列第二个如果也是0,就会有2^2 = 4种(不要nums[0],要nums[0],不要nums[1],要nums[1]都行),所以有多少个0,就有2多少次方个方法。
4.遍历顺序:上下左右,左右上下都行。
5.举例推导dp数组
Java代码如下:
//二维数组
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for(int num : nums) {
sum += num;
}
if((sum + target) % 2 != 0) return 0;
if(Math.abs(target) > sum) return 0;
int bagSize = (sum + target) / 2;
int[][] dp = new int[nums.length][bagSize + 1];
int zeroN = 0;
if(nums[0] <= bagSize) dp[0][nums[0]] = 1;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 0) {
zeroN++;
}
dp[i][0] = (int) Math.pow(2, zeroN);
}
for(int i = 1; i < nums.length; i++) {
for(int j = 1; j <= bagSize; j++) {
if(j >= nums[i]) {
dp[i][j] = dp[i - 1][j] + dp[i - 1][j -nums[i]];
}else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[nums.length - 1][bagSize];
}
}
//一维数组
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for(int num : nums) {
sum += num;
}
if((sum + target) % 2 != 0) return 0;
if(Math.abs(target) > sum) return 0;
int bagSize = (sum + target) / 2;
int[] dp = new int[bagSize + 1];
dp[0] = 1;
for(int i = 0; i < nums.length; i++) {
for(int j = bagSize; j >= nums[i]; j--) {
dp[j] += dp[j -nums[i]];
}
}
return dp[bagSize];
}
}
总结:一维数组的形式初始化只需要dp[0] = 1就行了,想象下nums[0]为0时,j = 0时递推公式dp[j] += dp[j -nums[i]];依旧可以用,此时相当于dp[0]+dp[0] = 2了。
474.一和零
题目链接:474.一和零
文档讲解︰代码随想录(programmercarl.com)
视频讲解︰一和零
日期:2024-10-10
Java代码如下:
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int[][] dp = new int[m + 1][n + 1];
int oneNum, zeroNum;
for (String str : strs) {
oneNum = 0;
zeroNum = 0;
for (char ch : str.toCharArray()) {
if (ch == '0') {
zeroNum++;
} else {
oneNum++;
}
}
for (int i = m; i >= zeroNum; i--) {
for (int j = n; j >= oneNum; j--) {
dp[i][j] = Math.max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
}
}
}
return dp[m][n];
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构