leetcode面试8.10 硬币

leetcode面试8.10 硬币

题目

给定数量不限的硬币,币值为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

思路

先来一个二维数组


   1 2 3 4 5 ....n
1  1 1 1 1 1 ....1
5  1 1 1 1 2 ....
10 1 1 1 1 2 ....
25 1 1 1 1 2 ....

先有个印象哈,虽然这个很简单,左边是硬币,上边是要求给定的n
1>思路一:二维数组实现dp


dp[][]=new dp[5][n+1];coins={1,5,10,25}
这里二维数组i的位置是5而不是4,是因为下面i的循环要从1开始,如果从0开始就会越界,想不通就可以看下面的代码
则有一些位置是可以初始化的,比如第一列将其初始化为0
随后开始正常的二层循环
这个循环一定是硬币这边在外层,这样代表的是现在能用的硬币是哪个(背包问题的解法就是此刻能往里面放的是哪个东西,就是这里能用的硬币是哪个),你如果放在里面就乱了
里面的状态方程应当是
如果当前的数值小于当前的coins[i-1],则输入的是上面那一个dp[i-1][j]
否则dp[i][j]=dp[i-1][j]+dp[i][j-coins[i-1]]这里并没有用max什么的,这里是求次数,自然是用+的
从这里我们就考虑到了一个问题,假如是n=5,现在也正好用到了硬币5
那么上面的dp[i][j]=dp[i-1][j]+dp[i][j-coins[i]]就变成了dp[1][5]=dp[1][5]+dp[5][0],后面这个变成了0
显然是不太合适的
因为这个的含义应该是刚好使用了一个硬币5
所以就发现了在这动态规划中0位置的元素不能让他们躺尸了,其现在代表的含义是恰好可以用一张的情况,所以将其全部变成1
for(int i=0;i<coins.length;i++) dp[i][0]=1;

        int[][] dp=new int[5][n+1];
        int[] coins={1,5,10,25};
        for (int i = 0; i <5 ; i++) {
           dp[i][0]=1;
        }
        for (int i = 1; i <5 ; i++) {
            for (int j = 1; j <=n ; j++) {
               if (j<coins[i-1]){//注意这里是i-1,因为i是从1开始的
                    dp[i][j]=dp[i-1][j];
               }else {
                    dp[i][j]=(dp[i-1][j]+dp[i][j-coins[i-1]])%1000000007;
               }
           }
       }
        return dp[4][n];

2> 思路2:采用一维数组实现dp


	虽是一维数组本质也是dp的思想
    和上面个dp[i][0]=1的情况一样,这里的dp[0]=1,也是用来表示用这一个硬币的情况下
    dp[]=new dp[n+1];
    coins={1,5,10,25};
    这里的方程依然是coins的循环在外面,n在里面
    dp[i]=dp[i]+dp[i-coins[j]]

int[] dp = new int[n + 1];
        dp[0] = 1;
        int[] coins = {1, 5, 10, 25};
        for (int coin : coins) {
            for (int i = 1; i <=n; i++) {
                if (i < coin) {
                    dp[i] = dp[i];//这里可不能写break,那样的话就是在coin=x的时候,一开始这个循环就结束了,不会进行后面的操作了
                //所以就可以理解,这里直接将i从coin开始,就不用有这个问题了,因为比coin小的都是上一个coin的,不变,变化是从等于coin的这一个开始,也就是说i=coin的话,这个if语句删了就可以
                } else {
                    dp[i] = (dp[i] + dp[i - coin]) % 1000000007;
                }
            }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值