简单编程题目连载(五)——找零钱
2017-01-15 22:05
295 查看
接着上一篇的经典动态规划题目来说。
上一篇的解题方法为暴力求解法,暴力求解法之所以称之为暴力求解法,是因为其中存在着大量的冗余,比如:
对于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相同的递归函数,也就是说,进行了大量的重复计算。所以优化的第一个思路就是将这些重复计算记录下来,下次遇到之前计算过的结果,直接查找调用。这就是记忆搜索法。这是一个空间换时间的方法。
接下来看代码:
以上为找零钱题目的记忆搜索法求解过程。
上一篇的解题方法为暴力求解法,暴力求解法之所以称之为暴力求解法,是因为其中存在着大量的冗余,比如:
对于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-1背包问题
- 简单编程题目连载(三)
- 简单编程题目连载(十)——公共最长子序列
- 简单编程题目连载(十三)——拓扑结构相同子树判断
- 简单编程题目连载(七)——经典台阶问题
- 简单编程题目连载(八)——最短路径问题
- 简单编程题目连载(十五)——找二叉树中的最大搜索二叉子树
- 简单编程题目连载(二)
- PAT基础编程题目集 4-8 简单阶乘计算
- 一道简单的编程题目
- 串的简单处理 在实际的开发工作中,对字符串的处理是最常见的编程任务。 本题目即是要求程序对用户输入的串进行处理。
- 编程题目的简单练习
- 简单GUI编程题目
- PAT 基础编程题目集 4-1 简单输出整数
- DE1-SoC初学者——PL部分编程实录——简单LED——连载01(图片上传失败,重新做图中...)
- 微软编程之美的资格赛,这么简单的题目害我编了一个多小时——传话游戏