LeetCode(C++)-动态规划-完全背包(零钱兑换 II、组合总和 Ⅳ、零钱兑换、完全平方数、单词拆分)

518. 零钱兑换 II

代码:

class Solution {	//518. 零钱兑换 II
	//动态规划五部曲:
	//1. 确定dp数组以及下标的含义:总金额为j时,组合数的方法为dp[j]
	//2. 确定递推公式:dp[j]+=dp[j-coins[i]]
	//3. dp数组如何初始化:dp[0]=1,其他初始化为0
	//4. 确定遍历顺序:外层for循环遍历硬币,内层for循环从小到大遍历背包容量
	//5. 举例推导dp数组:
public:
	int change(int amount, vector<int>& coins) {
		vector<int> dp(amount + 1, 0);
		dp[0] = 1;
		for (int i = 0; i < coins.size(); ++i) {
			for (int j = coins[i]; j <= amount; ++j) {
				dp[j] += dp[j - coins[i]];
			}
		}
		return dp[amount];
	}
};

377. 组合总和 Ⅳ

代码:

class Solution {	//377. 组合总和 Ⅳ
	//动态规划五部曲:
	//1. 确定dp数组以及下标的含义:目标整数为j时,总和为j的元素组合个数为dp[j]
	//2. 确定递推公式:dp[j]+=dp[j-nums[i]]
	//3. dp数组如何初始化:dp[0]=1,其他为0
	//4. 确定遍历顺序:外层for循环遍历背包容量j,内层for循环遍历物品(nums[i])
	//5. 举例推导dp数组:
public:
	int combinationSum4(vector<int>& nums, int target) {
		vector<int> dp(target + 1, 0);
		dp[0] = 1;
		for (int j = 0; j <= target; ++j) {
			for (int i = 0; i < nums.size(); ++i) {
				if (j - nums[i] >= 0 && dp[j] < INT_MAX - dp[j-nums[i]]) 
					dp[j] += dp[j - nums[i]];
			}
		}
		return dp[target];
	}
};

322. 零钱兑换

代码:

class Solution {	//322. 零钱兑换
	//动态规划五部曲:
	//1. 确定dp数组以及下标的含义:凑成总金额j所需的最少的硬币个数是dp[j]
	//2. 确定递推公式:dp[j]=min(dp[j],dp[j-coins[i]]+1);
	//3. dp数组如何初始化:dp[0]=0,其余为INT_MAX
	//4. 确定遍历顺序:外层for循环遍历物品(coins[i]),内层for循环从小到大遍历背包容量j
	//5. 举例推导dp数组:
public:
	int coinChange(vector<int>& coins, int amount) {
		vector<int> dp(amount + 1, INT_MAX);
		dp[0] = 0;
		sort(coins.begin(), coins.end());
		for (int i = 0; i < coins.size(); ++i) {
			for (int j = coins[i]; j <= amount; ++j) {
				if (dp[j - coins[i]] != INT_MAX)
					dp[j] = min(dp[j], dp[j - coins[i]] + 1);
			}
		}
		if (dp[amount] == INT_MAX) return -1;
		return dp[amount];
	}
};

279. 完全平方数

代码:

class Solution {	//279. 完全平方数
	//动态规划五部曲:
	//1. 确定dp数组以及下标的含义:和为 j 的完全平方数的最少数量为dp[j]
	//2. 确定递推公式:dp[j] = min(dp[j], dp[j - i*i] + 1);
	//3. dp数组如何初始化:dp[0]=0,其余为INT_MAX
	//4. 确定遍历顺序:外层for循环遍历物品(从1到sqrt(n)),内层for循环从小到大遍历背包容量j
	//5. 举例推导dp数组:
public:
	int numSquares(int n) {
		vector<int> dp(n + 1, INT_MAX);
		int numMax = sqrt(n);
		dp[0] = 0;
		for (int i = 1; i <= numMax; ++i) {
			for (int j = i*i; j <= n; ++j) {
				dp[j] = min(dp[j], dp[j - i*i] + 1);
			}
		}
		return dp[n];
	}
};

139. 单词拆分

代码:

class Solution {	//139. 单词拆分
	//动态规划五部曲:
	//1. 确定dp数组以及下标的含义:dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。
	//2. 确定递推公式: if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true
	//3. dp数组如何初始化:d[0]=true,其他为false
	//4. 确定遍历顺序:遍历背包放在外循环,将遍历物品放在内循环
	//5. 举例推导dp数组:
public:
	bool wordBreak(string s, vector<string>& wordDict) {
		unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
		vector<bool> dp(s.size() + 1, false);
		dp[0] = true;
		for (int i = 1; i <= s.size(); ++i) {
			for (int j = 0; j < i; ++j) {
				string word = s.substr(j, i - j);
				if (wordSet.find(word) != wordSet.end() && dp[j]) {
					dp[i] = true;
				}
			}
		}
		return dp[s.size()];
	}
};

参考资料:

代码随想录

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海螺蜜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值