换零钱问题迭代解法

搬运自 http://blog.sina.com.cn/s/blog_7daf3d040101od8p.html

问题来源 SICP

线性递归和迭代(尾递归)
计算机程序的构造与解释(SICP)递归与迭代

计算机程序的构造与解释(SICP)递归与迭代


树形递归(优化尽量先从瓶颈优化,尽量先从算法优化)
指数级 线性

计算机程序的构造与解释(SICP)递归与迭代

这个结果不能说树形递归是无用的,对于层级数据结构而不是数,就会发现树形递归是很自然并强大的工具。即使对与数的计算,它也可能帮助我们理解和设计程序,更加的直观。

实例:对于1美元,给定1/2美元、1/4美元、10美分、5美分、1美分,将1美元换成零钱,有多少种方式?更一般的问题是,对于任意数量的现金,有多少种换零钱的方式?

对于现金a,硬币种类数目n,换零钱的方式数目等于:
  • 用除了第一种硬币之外的硬币换的数目,加上
  • 把现金a-d用n种硬币换的数目,d为第一种硬币的面额
这样逐步缩小问题的规模,但应有下列规则:
  • 当a=0,返回换零钱方式数目为1
  • 当a<0,返回换零钱方式数目为0
  • 当n=0,返回换零钱方式数目为0
转换为代码:
( define (count-change  amount)
  (cc  amount  5))
( define (cc  amount  kinds-of-coins)
  ( cond ((=  amount  0 1)
           (( or (<  amount  0) (=  kinds-of-coins  0))  0)
           ( else (+  (cc  amount
                              (-  kinds-of-coins  1))
                        (cc  (-  amount
                                   (first-denomination  kinds-of-coins))
                               kinds-of-coins)))))
( define (first-denomination  kinds-of-coins)
  ( cond ((=  kinds-of-coins  1 1)
           ((=  kinds-of-coins  2 5)
           ((=  kinds-of-coins  3 10)
           ((=  kinds-of-coins  4 25)
           ((=  kinds-of-coins  5 50)))

树形递归会有很多冗余计算,但也同样直观,易于理解。如果要想一个其他的更好的算法,就不那么容易了。对于冗余,可以把计算过的过程保存下来,下次再计算时查看是否计算过,避免重复计算。

临时想了一个迭代的算法,结果很不直观啊
计算机程序的构造与解释(SICP)递归与迭代

//
博主的评论:
第二个方法相当于先用1分填满;然后清空加进去一个5分,再执行同样的操作,直至5分这个位置也被填满;接着扔进去一个10分.... 以此一直到50分也被填满。同时巧妙地用sum记录总数
另外, ((> temp amount) (cc-iter-1 n1 n2 n3 n4 n5 amount sum))) 很漂亮,比如说如果是1001分,20个50分和1个1分恰好覆盖,这时再多一个50分就超出总数了,于是次数再跳回cc-iter-1,n2到n5都为0,直接print sum。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值