• 509.斐波那契数 | 322.零钱兑换


    509.斐波那契数

    斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

    F(0) = 0,F(1) = 1
    F(n) = F(n - 1) + F(n - 2),其中 n > 1
    给定 n ,请计算 F(n) 。

    示例 1:

    输入:n = 2
    输出:1
    解释:F(2) = F(1) + F(0) = 1 + 0 = 1
    示例 2:

    输入:n = 3
    输出:2
    解释:F(3) = F(2) + F(1) = 1 + 1 = 2
    示例 3:

    输入:n = 4
    输出:3
    解释:F(4) = F(3) + F(2) = 2 + 1 = 3

    思路:动态规划

    先写状态转移方程,然后写出暴力解法,再添加备忘录,完成剪枝

    1. class Solution {
    2. public:
    3. int fib(int n) {
    4. int cur=0;
    5. int next=1;
    6. if(n==0||n==1)
    7. return n;
    8. int res=0;
    9. for(int i=2;i<=n;i++)
    10. {
    11. res=cur+next;
    12. cur=next;
    13. next=res;
    14. }
    15. return res;
    16. }
    17. };

    322.零钱兑换

    给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

    计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

    你可以认为每种硬币的数量是无限的。

    示例 1:

    输入:coins = [1, 2, 5], amount = 11
    输出:3 
    解释:11 = 5 + 5 + 1
    示例 2:

    输入:coins = [2], amount = 3
    输出:-1
    示例 3:

    输入:coins = [1], amount = 0
    输出:0

    思路:动态规划

    先写状态转移方程,然后写出暴力解法,再添加备忘录,完成剪枝

    用dp函数自顶向下做 

    1. class Solution {
    2. public:
    3. //count=1+min(coinChange([1,2,5],11-1),coinChange([1,2,5],11-2),coinChange([1,2,5],11-5))
    4. //helper()函数定义:输入一个amount,返回可以凑成它的最少硬币个数
    5. int coinChange(vector<int>& coins, int amount) {
    6. vector<int> memo(amount+1,INT_MIN);//备忘录
    7. int ans=helper(coins,amount,memo);
    8. return ans;
    9. }
    10. int helper(vector<int>& coins,int amount,vector<int>& memo)
    11. {
    12. if(amount==0)
    13. return 0;
    14. if(amount<0)//amount小于0,说明凑不出来
    15. return -1;
    16. if(memo[amount]!=INT_MIN)
    17. return memo[amount];
    18. int res=INT_MAX;
    19. for(int coin:coins)
    20. {
    21. //计算子问题的结果
    22. int count=helper(coins,amount-coin,memo);
    23. if(count==-1)//说明子问题凑不出来,就跳过
    24. continue;
    25. res=min(res,count);
    26. }
    27. if(res==INT_MAX)
    28. memo[amount]=-1;
    29. else
    30. memo[amount]=res+1;
    31. return memo[amount];
    32. }
    33. };

    用dp数组自底向上做:

    1. class Solution {
    2. public:
    3. int coinChange(vector<int>& coins, int amount) {
    4. //设置为amount+1是因为,全用1元硬币凑amount需要amount枚,所以amount+1比最大枚数还要大
    5. //但不能设置为INT_MAX,不然INT_MAX和INT_MAX+1,是无法比较出最小值的
    6. vector<int> dp(amount+1,amount+1);
    7. dp[0]=0;
    8. for(int i=1;i<=amount;i++)
    9. {
    10. for(int coin:coins)
    11. {
    12. if(i-coin<0)
    13. {
    14. continue;
    15. }
    16. dp[i]=min(dp[i],dp[i-coin]+1);
    17. }
    18. }
    19. return dp[amount]==amount+1?-1:dp[amount];
    20. }
    21. };
  • 相关阅读:
    H3CNE V7.0 视频教程
    milvus upsert流程源码分析
    Java正则表达式之捕获组奥秘探索
    佳易王美发店会员管理系统软件,操作简单扣次或充值消费,支持会员短信功能
    Go基础16-defer的运作机制及常见用法
    基于Python实现多项式拟合正弦函数
    Spark 源码分析-FIFO/FAIR调度策略
    基于Java中的SSM框架实现菜匣子优选系统项目【项目源码+论文说明】计算机毕业设计
    linux之进程地址空间
    一文速通Nginx网关与gateway网关区分
  • 原文地址:https://blog.csdn.net/weixin_50437588/article/details/126415784