leetCode 322.零钱兑换 完全背包 + 动态规划 + 记忆化搜索 + 递推 + 空间优化

关于此题 我的往期文章 :LeetCode 322.零钱兑换 完全背包 + 动态规划_呵呵哒( ̄▽ ̄)"的博客-CSDN博客https://heheda.blog.csdn.net/article/details/133386579看本期文章时,可以先回顾一下动态规划入门知识和完全背包理论和实战:

0-1背包 完全背包 + 至多/恰好/至少 + 空间优化 + 常见变形题(实战力扣题)-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/134210521?spm=1001.2014.3001.5501leetCode 198.打家劫舍 动态规划入门:从记忆化搜索到递推-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/134179583?spm=1001.2014.3001.5501给你一个整数数组 coins,表示不同面额的硬币;以及一个整数 amount,表示总金额 。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何 一种硬币组合能组成总金额 ,返回 -1 。你可以认为每种硬币的数量是无限的。


(1)递归

cpp 复制代码
class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size();
        function<int(int,int)> dfs=[&](int i,int c) -> int {
            if(i < 0) {
                if(c == 0) return 0;
                else return INT_MAX/2;// 除 2 是防止下面 + 1 溢出
            }
            if(c < coins[i]) return dfs(i-1,c);
            return min(dfs(i-1,c),dfs(i,c-coins[i])+1);     
        };
        int ans = dfs(n-1,amount);
        return ans<INT_MAX/2?ans:-1;
    }
};

(2)递归搜索 + 保存计算结果 = 记忆化搜索

cpp 复制代码
class Solution {
public:
    // 记忆化搜索
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size(),memo[n+1][amount+1];
        memset(memo,-1,sizeof(memo));
        function<int(int,int)> dfs=[&](int i,int c) -> int {
            if(i < 0) {
                if(c == 0) return 0;
                else return INT_MAX/2;// 除 2 是防止下面 + 1 溢出
            }
            int& res = memo[i][c];
            if(res != -1) return res;
            if(c < coins[i]) return res=dfs(i-1,c);
            return res=min(dfs(i-1,c),dfs(i,c-coins[i])+1);     
        };
        int ans = dfs(n-1,amount);
        return ans<INT_MAX/2?ans:-1;
    }
};
  • 时间复杂度:O(n * amount)
  • 空间复杂度:O(n * amount)

(3)1:1 翻译成递推

cpp 复制代码
class Solution {
public:
    // 1:1 翻译成递推
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size(),f[n+1][amount+1];
        memset(f,0x3f,sizeof(f));
        f[0][0]=0;
        for(int i=0;i<n;i++) {
            for(int c=0;c<=amount;c++) {
                if(c<coins[i]) f[i+1][c] = f[i][c];
                else f[i+1][c] = min(f[i][c],f[i+1][c-coins[i]]+1); 
            }
        }
        int ans = f[n][amount];
        return ans<0x3f3f3f3f?ans:-1;
    }
};
  • 时间复杂度:O(n * amount)
  • 空间复杂度:O(n * amount)

(4)空间优化:两个数组(滚动数组)

cpp 复制代码
class Solution {
public:
    // 空间优化:两个数组(滚动数组)
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size(),f[2][amount+1];
        memset(f,0x3f,sizeof(f));
        f[0][0]=0;
        for(int i=0;i<n;i++) {
            for(int c=0;c<=amount;c++) {
                if(c<coins[i]) f[(i+1)%2][c] = f[i%2][c];
                else f[(i+1)%2][c] = min(f[i%2][c],f[(i+1)%2][c-coins[i]]+1); 
            }
        }
        int ans = f[n%2][amount];
        return ans<0x3f3f3f3f?ans:-1;
    }
};
  • 时间复杂度:O(n * amount)
  • 空间复杂度:O(amount)

(5)空间优化:一个数组

cpp 复制代码
class Solution {
public:
    // 空间优化:两个数组(滚动数组)
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size(),f[amount+1];
        memset(f,0x3f,sizeof(f));
        f[0]=0;
        for(int i=0;i<n;i++) {
            for(int c=coins[i];c<=amount;c++) {
                f[c] = min(f[c],f[c-coins[i]]+1); 
            }
        }
        int ans = f[amount];
        return ans<0x3f3f3f3f?ans:-1;
    }
};
  • 时间复杂度:O(n * amount)
  • 空间复杂度:O(amount)
相关推荐
Cccp.1236 小时前
【leetcode】(十三)大数据处理
数据结构·算法·leetcode
wzdark6 小时前
动态规划算法的状态转移矩阵可视化分析5
算法·矩阵·动态规划
Pniubi6 小时前
力扣70爬楼梯
数据结构·算法·leetcode
所以遗憾是什么呢?18 小时前
【题解】Educational Codeforces Round 195 (Rated for Div. 2) ABCDE
c++·动态规划·acm·icpc·ccpc·xcpc·codeforecs
Navigator_Z21 小时前
LeetCode //C - 1293. Shortest Path in a Grid with Obstacles Elimination
c语言·算法·leetcode
Nil2081 天前
leetcode 64最小路径和
算法·leetcode·职场和发展
Nil2081 天前
leetcode 72编辑距离
算法·leetcode·职场和发展
Nil2081 天前
leetcode 136只出现一次的数字
leetcode·哈希算法·散列表
lvwangshu1 天前
川剧复演 题解
动态规划·题解·技巧·性质题·思维好题
局部有解1 天前
LeetCode Hot100 438 找到字符串中所有字母异位词
c++·算法·leetcode