ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

[算法练习及思路-程序员面试金典(Java解法)]No51.硬币(完全背包问题+优化空间)

2020-11-26 17:59:49  阅读:242  来源: 互联网

标签:10 Java 硬币 int 金典 coins 25 No51 dp


题号:no51

题目名:硬币

原题URL:https://leetcode-cn.com/problems/coin-lcci/

题目描述

硬币。给定数量不限的硬币,币值为25分、10分、5分和1分,编写代码计算n分有几种表示法。(结果可能会很大,你需要将结果模上1000000007)

示例

示例 1:

 输入: n = 5
 输出:2
 解释: 有两种方式可以凑成总金额:
5=5
5=1+1+1+1+1

示例 2:

 输入: n = 10
 输出:4
 解释: 有四种方式可以凑成总金额:
10=10
10=5+5
10=5+1+1+1+1+1
10=1+1+1+1+1+1+1+1+1+1

限制

  • 注意:

    你可以假设:

    • 0 <= n (总金额) <= 1000000

思路

1.经典完全背包问题,容量固定,物品无限放

2.因为硬币可以无限放,所以以硬币做外层循环,避免重复

3.状态转移方程就是dp[ i ] [ j ] = (dp[ i - 1 ] [ j ] + dp [i] [j - coins[i-1]]),当如果可以用该硬币

如果不用该硬币,那就是上一个硬币的方法数就行dp[ i ] [ j ] = dp[ i - 1 ] [ j ]

4.可以将二维完全背包变成一维

解题代码

class Solution {
    public int waysToChange(int n) {
        //1000000007
        //硬币类型为25,10,5,1四种类型,总共是n元
        //当总值等于n的时候,其实一共有四种方法能达到
        //1.前面的硬币总值为n-25,最后一个硬币为25元
        //2.前面的硬币总值为n-10,最后一个硬币为10元
        //3.前面的硬币总值为n-5,最后一个硬币为5元
        //4.前面的硬币总值为n-1,最后一个硬币为1元
        //完全背包问题
        int mod = 1000000007;
        int[] coins = {1,5,10,25};
        int[][] dp = new int[coins.length+1][n+1];
        //先初始化所有硬币的取出方式都为1
        for (int i = 0; i < dp.length; i++) {
            dp[i][0] = 1;
        }

        for (int i = 1; i <= coins.length; i++) {
            for (int j = 1; j < n + 1; j++) {
                //遍历硬币
                dp[i][j] = dp[i - 1][j];
                if (j - coins[i-1] >= 0) dp[i][j] = (dp[i - 1][j] + dp[i][j - coins[i-1]])%mod;
            }
        }
        return dp[coins.length][n];
    }
}

优化

1.优化思路就是讲二维变成一维,要去掉的维度要对原来没有影响

2.也就是说,可以作为滚动数组来操作

3.观察二维,可以看到状态方程式都是(i,j)和(i-1,j)在挂钩,其实用前面一维做滚动就够用了

class Solution {
    public int waysToChange(int n) {
        //完全背包问题
        int mod = 1000000007;
        int[] coins = {1,5,10,25};
        int[][] dp = new int[coins.length+1][n+1];
        //先初始化所有硬币的取出方式都为1
		dp[0] = 1;

        for (int i = 1; i <= coins.length; i++) {
            for (int j = 1; j < n + 1; j++) {
                //遍历硬币
                if (j - coins[i-1] >= 0) dp[j] = (dp[j] + dp[j - coins[i-1]])%mod;
            }
        }
        return dp[coins.length][n];
    }
}

标签:10,Java,硬币,int,金典,coins,25,No51,dp
来源: https://blog.csdn.net/qq_41522089/article/details/110198743

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有