代码随想录算法训练营第43天 | 1049.最后一块石头的重量II 494.目标和 474.一和零

最后一块石头的重量II

代码随想录算法训练营第43天 | 1049.最后一块石头的重量II 494.目标和 474.一和零_第1张图片
若要让剩余的石头重量最小,只需要将石头分成重量近似的两堆。因此我们将石头总重量的一半作为背包容量,希望装进来的石头能尽量将背包填满。这就转化成了分割等和子集那道题的思想。

class Solution{
public:
	int lastStoneWeightII(vector<int>& stones) {
		int sum = 0;
		for(int weight : stones) {
			sum += weight;
		}
		int target = sum / 2;
		vector<int> dp(target + 1, 0);
		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]);
			}
		}
		// target是向下取整,所以sum-dp[target]一定比dp[target]大,且二者尽量接近
		return sum - dp[target] - dp[target];
	}
};

目标和

代码随想录算法训练营第43天 | 1049.最后一块石头的重量II 494.目标和 474.一和零_第2张图片
原理上不难理解,target 是在数组中添加符号之后的结果,那么 (sum + target) / 2 就是将负号的元素抵消掉之后得到的正数之和。仍然可以转化为01背包问题,从数组中挑选数字使之加和等于 (sum + target) / 2,每个数字只能使用一次。
但有一些小问题需要注意,这道题中给的数组中的数字都是大于等于0的。所以如果加和小于target 的绝对值,证明所有都是正数或者所有数字添加负号都不能达到 target,这时直接返回0。另外sum + target一定是一个偶数,不然也没法添加负号得到 target,这种情况也要返回0。

class Solution {
public:
	int findTargetSumWays(vector<int>& nums, int target) {
		int sum = 0;
		for(int num : nums) {
			sum += num;
		}
		if(sum < abs(target))  return 0;
		if((sum + target) % 2)  return 0;
		int bagSize = (sum + target) / 2;
		vector<int> dp(bagSize + 1, 0);  // dp[i]表示背包容量为i时数字的选择方式数量
		dp[0] = 1;  // 当背包容量为0时,只有都不选择这一种方式
		for(int i = 0; i < nums.size(); i++) {
			for(int j = bagSize; j >= nums[i]; j--) {
				dp[j] += dp[j - nums[i]];
			}
		}
		return dp[bagSize];
	}
};

一和零

代码随想录算法训练营第43天 | 1049.最后一块石头的重量II 494.目标和 474.一和零_第3张图片
这道题就是从两个维度限制了背包大小,1的数量和0的数量。另外它要找的是字符串数目最多的子集,所以每个字符串的价值就是1,价值最大那么字符串数目就越多。

class Solution{
public:
	int findMaxForm(vector<string>& strs, int m, int n) {
		// 01两个维度来限制背包大小
		vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
		for(string str : strs){
			int ones = 0;
			int zeros = 0;
			for(char ch : str) {
				if(ch == '1')  ones++;
				else zeros++;
			}
			for(int i = m; i >= zeros; i--) {
				for(int j = n; j >= ones; j--) {
					dp[i][j] = max(dp[i][j], dp[i - zeros][j - ones] + 1);
				}
			}
		}
		return dp[m][n];
	}
};

你可能感兴趣的:(算法)