给定一定金额的钱,求换得后的硬币个数最少


/**
 *
 *  拥有不同面值的货币,求,换一定面值的钱,用的货币的 数目 最少
 *
 */
public class MakingChange {


   // 用于方法二中纪录求过的值,避免重复计算
    static int[] history = null;

    public static void main(String[] args) {

        int[] coinKinds = {1, 3, 5}; // 货币的种类,与 币值,此处共有三种货币,面值分别为 1,3,5

        int values = 12; // 需要兑换的面值

        // 调用方法 1
        method1(coinKinds,values);

        // 调用方法 2 
        method2(coinKinds,12);

        // 输出方法 2 求的的值
        for (int i = 0; i < history.length; i++) {
            System.out.print(" " + history[i]);
        }


    }

    // 第一种方法,每种面值的依次计算,先计算面值 0 ,然后 1, 然后 2 ,然后3 。。。。 但是每种面值的计算依赖于前面的计算结果
    // temp1 = choices[ i - 面值种类[1] ] + 1
    // temp2 = choices[ i - 面值种类[2] ] + 1
    //            .......
    // 最后 choices[i] 中的值,为上述 temp 值中的最小值,此过程在程序中通过一个循环实现。
    //
    public static void method1(int[] coinKinds, int values) {

        int[] choices = new int[values];   // 一维数组,choices[i] 表示的是 兑换 面值 i 可以有 choices[i] 种兑换方式

        // 求解具体每种面值的兑换方式 i 遍历的是从 0 开始到 values 的面值
        for (int i = 0; i < values; i++) {
            int mincoins = i; // 最基本的兑换方式就是,全部用 1 元的来兑,所以最多就是 mincoins 种方式
            // j 遍历的是不同币种的个数
            for (int j = 0; j < coinKinds.length; j++) {
                if (coinKinds[j] <= i) {
                    int temp = choices[i - coinKinds[j]] + 1;
                    if (mincoins > temp) {
                        mincoins = temp;
                    }
                }
            }
            choices[i] = mincoins;
        }
        // 输出查看结果
        System.out.println("面值:兑换方式");
        for (int i = 0; i < choices.length; i++) {
            System.out.println( " " + i + " :  " + choices[i]);
        }
    }

    // 第二种方法,采用递归的方法,history 中纪录的是每次求的的值
    // 避免重复进行递归计算
    public static void method2(int[] coinKinds, int values) {

        history = new int[values+1];
        history[0] = 0;
        history[1] = 1;
        history[2] = 2;

        int mincoins = getMincoins(coinKinds, values);
        System.out.println(mincoins);
    }

    private static int getMincoins(int[] coinKinds, int value) {

        if (value <=0) {
            return 0;
        }
        if (value == 1) {
            return 1;
        }
        if (value == 2) {
            return 2;
        }
        int mincoins = value;

        for (int coinKind = 0; coinKind < coinKinds.length; coinKind++) {
            // 找到前一个需要依赖的值
            int preCondition = value - coinKinds[coinKind];
            if (preCondition < 0) {
                break;
            }
            int temp;
            // 递归算法算过的值,都纪录到 history 中,避免重复计算
            if (history[preCondition] != 0) {
                temp = history[preCondition];
            }
            else{
                temp = getMincoins(coinKinds, preCondition);
            }
            if (mincoins > temp) {
                mincoins = temp;
            }
        }
        history[value] = mincoins+1;
        return mincoins + 1;
    }

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值