简单编程题目连载(五)——找零钱

接着上一篇的经典动态规划题目来说。

上一篇的解题方法为暴力求解法,暴力求解法之所以称之为暴力求解法,是因为其中存在着大量的冗余,比如:

对于penny数组{5,10,25,1},目标金额为1000,来说,当使用0张5元,1张10元,进行接下来的递归计算,调用的函数为:res(penny,2,990)。而当使用2张5元,0张10元,进行接下来的递归计算,调用的函数为:res(penny,2,990)。

原解法中,递归计算的数组penny是不变的,每次改变的是递归函数的index和aim。而上述例子表明存在大量index和aim相同的递归函数,也就是说,进行了大量的重复计算。所以优化的第一个思路就是将这些重复计算记录下来,下次遇到之前计算过的结果,直接查找调用。这就是记忆搜索法。这是一个空间换时间的方法。

接下来看代码:

public int countType(int[] penny,int n,int aim){
    if(penny == null || n <= 0 || aim <= 0){
        return 0;
    }
    //声明一个二维数组  用来存重复的res(penny,index,aim);的结果
    int[][] map = new int[n+1][aim+1];
    res(penny,index,aim,map);
}
public int res(int[] penny,int index,int aim,int[][] map){
    int result = 0;
    //说明有值且不为0
    if(map[index][aim] > 0){
        return map[index][aim];
    }else if(map[index][aim] == -1){
        return 0;
    }else{//这个意思就是第一次遇到这个index和aim的组合
        result = aim == 0 ? 1 : 0;
        for(int i = 0;index < penny.length && penny[index]*i <= aim && aim > 0;i++){
            result += res(penny,index+1,aim-penny[index]*i,map);
        }
        //设置一个-1的目的是为了 区分 递归结果为0 的那些结果与数组初始化结果也为零冲突
        map[index][aim] = result == 0 ? -1 : result;
        return result;
    }
}

以上为找零钱题目的记忆搜索法求解过程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值