动态规划--完全背包
70. Climbing Stairs
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n+1, 0);
dp[0] = 1;
for(int i=0; i<=n; i++){
for(int j=1; j<=2; j++){
if(i>=j)
dp[i] += dp[i-j];
}
}
return dp[n];
}
};
322. Coin Change
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount+1, INT_MAX);
dp[0]=0;
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];
}
};
1.为了求得是最小值,dp数组初始化应为INT_MAX,dp[0] = 0
2.要加上条件if 不等于最大值以及-1的情况
3.明确排列数和组合数的区别
排列数,在意顺序(不同顺序的算新一组),所以先背包,在物品
组合数,不在意顺序(比如(1,2)和(2,1)是同一组)所以先遍历物品,在遍历背包
279. Perfect Squares
1.先遍历物品,在遍历背包
class Solution {
public:
int numSquares(int n) {
vector<int> dp(n+1, INT_MAX);
dp[0] = 0;
int sq = sqrt(n);
for(int i=1; i<= sq; i++){
for(int j=i*i; j<=n; j++){
if(dp[j-i*i] != INT_MAX){
dp[j] = min(dp[j], dp[j-i*i]+1);
}
}
}
return dp[n];
}
};
2.先遍历背包,在遍历物品
class Solution {
public:
int numSquares(int n) {
vector<int> dp(n+1, INT_MAX);
dp[0] = 0;
for(int i=1; i<= n; i++){
for(int j=1; j*j<=i; j++){
dp[i] = min(dp[i], dp[i-j*j]+1);
}
}
return dp[n];
}
};
哈希表
454. 4Sum II
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> record;
for(int num1:nums1){
for(int num2:nums2){
record[num1+num2]++;
}
}
int count = 0;
for(int num3:nums3){
for(int num4:nums4){
if(record.find(-num3-num4) != record.end()){
count += record[-num3-num4];
}
}
}
return count;
}
};
因为一种和肯能会出现多次,所以要用map-val记录出现的次数
383. Ransom Note
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int record[26]{0};
for(char val:ransomNote){
record[val- 'a']++;
}
for(char m:magazine){
record[m-'a']--;
}
for(int i=0; i<26; i++){
if(record[i] > 0)
return false;
}
return true;
}
};
15. 3Sum
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for(int i=0; i<nums.size(); i++){
if(nums[i] > 0){
return res;
}
if(i>0 && nums[i] == nums[i-1])
continue;
int left = i+1;
int right = nums.size()-1;
while(left < right){
if(nums[i]+nums[left]+nums[right] > 0){
right --;
}else if(nums[i]+nums[left]+nums[right] < 0){
left++;
}else{
res.push_back(vector<int> {nums[i], nums[left], nums[right]});
while(left < right && nums[right] == nums[right-1]) right--;
while(left < right && nums[left] == nums[left+1]) left++;
right--;
left++;
}
}
}
return res;
}
};
1.一定要注意去重
2.else里面要用while,因为有可能一直重复
文章讨论了动态规划在解决爬楼梯、找零钱、完美平方数等问题中的应用,强调初始化DP数组的重要性,以及在处理排列和组合问题时的策略差异。同时,提到了哈希表在四数之和问题和赎金信问题中的高效解决方案。
2277

被折叠的 条评论
为什么被折叠?



