算法学习|动态规划 LeetCode70. 爬楼梯 (进阶)、322. 零钱兑换、 279.完全平方数

动态规划

  • 一、爬楼梯(进阶)
    • 思路
    • 实现代码
  • 二、零钱兑换
    • 思路
    • 实现代码
  • 三、完全平方数
    • 思路
    • 实现代码

一、爬楼梯(进阶)

一步一个台阶,两个台阶,三个台阶,…,直到 m个台阶。问有多少种不同的方法可以爬到楼顶呢?

思路

1.dp[i]:爬到第i个台阶有dp[i]种方法
2.递推公式:dp[i] += dp[i - j]
3.初始化:dp[0] = 1 ,其他非零下标的dp数组初始化为0
4.遍历顺序:先遍历背包再遍历物品(求排列)

实现代码

class Solution {
public:
    int climbStairs(int n) {
        vector<int> dp(n + 1, 0);
        dp[0] = 1;
        for (int i = 1; i <= n; i++) { // 遍历背包
            for (int j = 1; j <= m; j++) { // 遍历物品
                if (i - j >= 0) dp[i] += dp[i - j];
            }
        }
        return dp[n];
    }
};

二、零钱兑换

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

思路

1.dp[j]:装满容量为j的背包最少用dp[j]件物品
2.递推公式: dp[j] = min(dp[j - coins[i]] +1,dp[j])
3.初始化: dp[0] = 0 非零下标的dp的数组初始化为INT_MAX
4.遍历顺序:先遍历物品再遍历背包(和元素顺序无关所以可颠倒)

实现代码

//先遍历物品再遍历背包
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 - coins[i]] + 1, dp[j]);
                }
            }
        }
        if(dp[amount] == INT_MAX) return -1;
        return dp[amount];
    }
};
//先遍历背包再遍历物品
class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount + 1, INT_MAX);
        dp[0] = 0;
        for (int i = 1; i <= amount; i++) {  
            for (int j = 0; j < coins.size(); j++) { 
                if (i - coins[j] >= 0 && dp[i - coins[j]] != INT_MAX ) {
                    dp[i] = min(dp[i - coins[j]] + 1, dp[i]);
                }
            }
        }
        if (dp[amount] == INT_MAX) return -1;
        return dp[amount];
    }
};

三、完全平方数

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。

思路

1.dp[j]:装满容量为j的背包最少需要dp[j]个元素
2.递推公式:dp[j] = min(dp[j - i*i]+1,dp[j])
3.初始化:dp[0] = 0 非零下标的dp的数组初始化为INT_MAX
4.遍历顺序:先遍历物品再遍历背包(和元素顺序无关所以可颠倒)

实现代码

//先遍历物品再遍历背包
class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n + 1, INT_MAX);
        dp[0] = 0;
        for(int i = 1; i * i <= n; i++) {
            for(int j = i * i; j <= n; j++) {
                dp[j] = min(dp[j - i * i] + 1, dp[j]);
            }
        }
        return dp[n];
    }
};
//先遍历背包再遍历物品
class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n + 1, INT_MAX);
        dp[0] = 0;
        for(int i = 0; i <= n; i++) {
            for(int j = 1; j * j <= i; j++) {
                dp[i] = min(dp[i - j * j] + 1, dp[i]);
            }
        }
        return dp[n];
    }
};

你可能感兴趣的:(#,算法学习,算法,动态规划,学习,leetcode,c++)