代码随想录算法训练营第三十四天| 70. 爬楼梯 (进阶) 322. 零钱兑换 279.完全平方数
70. 爬楼梯 (进阶)
要求:
可以一下爬1-2个台阶,问爬到N阶的时候有多少种方法
公式1: nums[n] = nums[n-1]+nums[n-2];
公式2: dp[n] +=dp[n-nums[i]];
代码:
1 // 爬楼梯的问题:依次只能爬1 2,满足N时,它的排列有多少种 2 // dp[n]:当爬够N阶台阶的时候一共有多少种方法 3 // 4 // dp[j] += dp[j-nums[i]] 5 // 6 7 int climbStairs(int n) { 8 if (n == 0) return 0; 9 vector<int> nums = { 1,2 }; 10 vector<int> dp(n + 1, 0); 11 dp[0] = 1; 12 13 for (int j = 0; j <= n; j++) 14 { 15 for (int i = 0; i < nums.size(); i++) 16 { 17 if(j>=nums[i]) 18 dp[j] += dp[j - nums[i]]; 19 } 20 } 21 22 return dp[n]; 23 }
322. 零钱兑换
要求:
满足target,最少的钱币的个数
递推公式:
dp[j] = min(dp[j], 1+dp[j-nums[i]])
注意初始化:
vector<int> dp(amount + 1, INT_MAX);
dp[0] = 0;
代码:
1 // 要求:返回凑成target的最小硬币个数 2 // 3 // 传统的背包问题:dp[n] 当容量为N时,最大的价值 4 // 5 // 变形的完全背包问题:dp[n] 当容量为N时,它的最小硬币个数 6 // 7 // 放当前硬币,不放当前硬币 8 // dp[j] = min(dp[j], 1+dp[j-nums[i]]) 9 // 10 int coinChange(vector<int>& coins, int amount) { 11 vector<int> dp(amount + 1, INT_MAX); 12 13 dp[0] = 0; 14 for (int i = 0; i < coins.size(); i++) 15 { 16 for (int j = coins[i]; j <= amount; j++) 17 { 18 //问题,取了之后,仍然可能无法满足,是因为 dp[] 19 if(dp[j-coins[i]] != INT_MAX) 20 dp[j] = min(dp[j], 1 + dp[j - coins[i]]); 21 } 22 } 23 24 if (dp[amount] >= INT_MAX) 25 return -1; 26 return dp[amount]; 27 }
279.完全平方数
思想类似
代码:
1 // 要求:给一个正数,需要在里面找出来完全平方数,同时需要这些完全平方数的和==N的最少数量 2 // 3 // 思路:物品:1-N内部的所有完全平方数 4 // 5 // dp[n] : 当和为N时,它的最少完全平方数的数量 6 // 7 // nums[i] 8 // 9 // dp[j] = min(dp[j], 1+dp[j-nums[i]]); 10 // 11 // 初始化: dp[0] = 0 其他为INT_MAX 12 // 13 int numSquares(int n) { 14 //找出nums 15 vector<int> nums; 16 for (int i = 1; i <= n;i++) 17 { 18 if (i * i <= n) 19 { 20 nums.push_back(i*i); 21 } 22 else 23 { 24 break; 25 } 26 } 27 28 vector<int> dp(n + 1, INT_MAX); 29 dp[0] = 0; 30 31 for (int i = 0; i < nums.size(); i++) 32 { 33 for (int j = nums[i]; j <= n; j++) 34 { 35 if (dp[j - nums[i]] != INT_MAX) 36 { 37 dp[j] = min(dp[j], 1 + dp[j - nums[i]]); 38 } 39 } 40 } 41 42 43 return dp[n]; 44 }