java 动态规划(找零钱)


java 动态规划(找零钱)

 

 

*************************

动态规划

 

算法描述:原问题可拆分为多个阶段进行,每个阶段都做出全局最优选择,并且当前阶段的选择与后续阶段选择无关(无后效性),以此得出原问题的全局最优解

 

应用举例:斐波那契数列

f(0)=0,
f(1)=1,
f(n)=f(n-1)+f(n-2), n>=2、n为自然数

可用解法:递归、递归+缓存(缓存重复计算的结果)、动态规划

 

动态规划求解:自底向上,依次计算f(2)、f(3) ... f(n)

全局最优:f(n)计算的值唯一,是全局最优解

无后效性:f(n)的值只与f(n-1)、f(n-2)有关,与f(n+1)、f(n+2)无关

 

 

*************************

示例:找零钱

 

问题描述

给定不同面额的硬币 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, 不需要找零

 

public class MyTest2 {

    private static final Map<Integer,Integer> map=new HashMap<>();

    public static int fun(int[] coins,int amount){
        if (amount<0){
            return -1;
        }

        if (amount==0){
            return 0;
        }

        if (coins.length==0){
            return -1;
        }

        int min=Integer.MAX_VALUE;
        for (int coin : coins) {
            int result = fun(coins, amount-coin);
            if (result != -1 && min > result) {
                min = result;
            }
        }

        if (min==Integer.MAX_VALUE){
            return -1;
        }else {
            return min+1;
        }
    }

    public static int fun2(int[] coins,int amount){
        if (map.get(amount)!=null){
            return map.get(amount);
        }

        if (amount<0){
            return -1;
        }

        if (amount==0){
            return 0;
        }

        if (coins.length==0){
            return -1;
        }

        int min=Integer.MAX_VALUE;
        for (int coin : coins) {
            int result = fun(coins, amount-coin);
            if (result != -1 && min > result) {
                min = result;
            }
        }

        int result=-1;
        if (min!=Integer.MAX_VALUE){
            result=min+1;
        }

        map.put(amount,result);
        return result;
    }

    public static int fun3(int[] coins, int amount){
        if (amount==0){
            return 0;
        }

        if (coins.length==0){
            return -1;
        }

        int[] a=new int[amount+1];
        for (int i=1;i<=amount;i++){
            a[i]=-1;
        }

        int min=coins[0];
        for (int value : coins){
            if (min>value){
                min=value;
            }
        }

        for (int i=0;i<=amount;i++){
            if ((i+min)>amount){
                break;
            }

            if (a[i]==-1){
                continue;
            }

            for (int value : coins){
                if ((i+value)<=amount&&(i+value)>0){
                    if (a[i+value]==-1||a[i+value]>a[i]+1){
                        a[i+value]=a[i]+1;
                    }
                }
            }
        }

        return a[amount];
    }

    public static void main(String[] args){
        int[] coins={1,2,5};
        int amount=21;

        System.out.println("递归求解:"+fun(coins,amount));
        System.out.println("递归缓存求解:"+fun2(coins,amount));
        System.out.println("动态规划求解:"+fun3(coins,amount));
    }
}

 

控制台输出

递归求解:5
递归缓存求解:5
动态规划求解:5

说明:动态规划的时间复杂度为o(n),计算使用的时间最短

 

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值