您的位置:首页 > 编程语言

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

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相同的递归函数,也就是说,进行了大量的重复计算。所以优化的第一个思路就是将这些重复计算记录下来,下次遇到之前计算过的结果,直接查找调用。这就是记忆搜索法。这是一个空间换时间的方法。

接下来看代码:

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;
}
}


以上为找零钱题目的记忆搜索法求解过程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程 递归