记得在SICP的第一章中,第1.2.2小节讲树形递归的时候,有一个实例是换零钱方式的统计。其中,作者是用的树形递归去求解的。但是,在这个实例的最后,作者又以找到一个效率更高的算法作为了一个非正式的作业,留给了读者作为挑战。起先在看完这节内容的时候,也是绞尽脑汁都想不出还能有什么更好的算法。但是,在看完了大半本书之后,无意中发现了一种方式。其实方法也很笨,就是枚举法,只是当时学到的语法太少了,不知道如何用scheme表达罢了,但是如果换成用python,那当时就应该能马上写出来的。好了 不废话了,直接上代码吧:

; 方法1 纯函数式实现
(define (count-change-1 amount denomination-list)(length (filter(lambda (data) (= amount (apply + (map * data denomination-list))))(accumulate(lambda (a-list b-list)(flatmap(lambda (a) (map (lambda (b) (cons a b)) b-list))a-list))(list '())(map(lambda (c) (enumerate-interval 0 c))(map (lambda (d) (floor (/ amount d))) denomination-list))))))

这是用纯函数式的编程风格实现的方法,还是那函数式编程的三大件:filter、map、accumulate。这里没有使用scheme自带的reduce而是用了书上定义的accumulate是有原因的,因为accumulate是用递归实现的,而reduce我猜测MIT-scheme是用迭代实现的,这里用accumulate能保证映射后结果的次序问题,而一旦使用了reduce则保证不了,从而导致错误。其他的过程像enumerate-interval,flatmap等等都在之前的文章中出现过了,书上也有,就不再放代码了。
然后是使用非函数式编程对上面代码的一点改进,效率会高一点。首先要定义一个核心的过程,嵌套映射:

; 定义嵌套映射
(define (nested-map mapping op keys-list)(define (rec keys-list args)(if (null? keys-list)(apply op (reverse args))(mapping(lambda (key)(rec (cdr keys-list) (cons key args)))(car keys-list))))(rec keys-list '()))

这里使用递归的方式实现了对与映射的嵌套,映射的种类由mapping参数传入,而keys-list则是由映射的基表所组成的表,即向量空间,这个表中的元素是所对应的每一层映射的基表。
有了它就可以改写上面的方法了,于是有了第二种效率更高一点的做法:

; 方法2 循环嵌套
(define (count-change-2 amount denomination-list)    (let ((count 0))(define (count-inc! . b)(if (= amount (apply + (map * b denomination-list)))(set! count (+ count 1))))        (nested-mapfor-eachcount-inc!(map(lambda (c) (enumerate-interval 0 c))(map (lambda (d) (floor (/ amount d))) denomination-list)))count))

虽然效率有那么一点提高,但是这里使用了局部变量,因此已经不再属于函数式编程了。但是基本的思路还是没改变:先枚举,再筛选。

SICP中关于兑换零钱的练习相关推荐

  1. 牛客题目——最长公共子串、最长回文子串、兑换零钱

    文章目录 题目1--最长公共子串 解题思路 代码实现 题目2--最长回文子串 解题思路 代码实现 题目3--兑换零钱 解题思路 代码实现 题目1--最长公共子串 给定两个字符串str1和str2,输出 ...

  2. 动态规划-背包问题、兑换零钱问题、旅行商问题

    背包问题 问题介绍 假定需要将Goods={g1,g1,-gn}放入容量为ALL的背包内,volumej代表第i个物品的体积,valuej代表第j个物品的价值.我们要把这些物品装进背包,这些物品的体积 ...

  3. java零钱兑换dp_兑换零钱(DP)

    题目描述 : 现有N元钱,兑换成小额的零钱,有多少种换法?币值包括1 2 5分,1 2 5角,1 2 5 10 20 50 100元. (由于结果可能会很大,输出Mod 10^9 + 7的结果) 输入 ...

  4. python整钱兑换零钱_LeetCode 零钱兑换

    零钱兑换 题目 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: 输入: ...

  5. 兑换零钱(一)——python

    给定数组arr,arr中所有的值都为正整数且不重复.每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数. 如果无解,请返回-1. 该题类 ...

  6. python整钱兑换零钱_使用Python完成收集变更的问题(DFS idea),凑,零钱,dfs,思想

    使用Python完成凑零钱问题(dfs思想) 题目描述 韩梅梅喜欢满宇宙到处逛街.现在她逛到了一家火星店里,发现这家店有个特别的规矩:你可以用任何星球的硬币付钱,但是绝不找零,当然也不能欠债.韩梅梅手 ...

  7. python整钱兑换零钱while语句_关于python:如何将钱(便士)转换为单个硬币?

    我的任务是 "编写一个功能selectCoins,要求用户输入金额 (以便士为单位),然后输出每种面额的硬币数量(从£ 2向下 到1p)应该用来精确地补足该金额(使用尽可能少的 硬币数量). ...

  8. [Leetcode][第322题][JAVA][零钱兑换][回溯][记忆化搜索][动态规划]

    [问题描述][中等] [解答思路] 1. 递归(超时) class Solution {int res = Integer.MAX_VALUE;public int coinChange(int[] ...

  9. Python版-LeetCode 学习:322 零钱兑换问题

    给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 说明:你可以认为每种硬币的数量是无 ...

  10. python换零钱_Python算法之零钱兑换问题的解法

    比如:顾客购物买37元东西,给了100元,要找63元,那最少数量就是1张50元,1张10元,3张1元,一共4张. 方法一: 贪心策略 解决这个问题,最直观的就是使用贪心策略.我们会从最大面值的钱开始, ...

最新文章

  1. 读javascript高级程序设计03-函数表达式、闭包、私有变量
  2. 【ios开发/Xcode】实现简易省会问答
  3. LINUX TOP,不是这样玩地!!!
  4. 华胜天成1.18亿美元收购美国GD公司
  5. 【Android 逆向】函数拦截 ( GOT 表数据结构分析 | 函数根据 GOT 表进行跳转的流程 )
  6. spark-1.5.2集群安装
  7. linux 内存 shared,Linux Shared Memory的查看与设置
  8. CENTOS MINI版安装tomcat9.0
  9. 为什么我要放弃javaScript数据结构与算法(第二章)—— 数组
  10. Java到LDAP教程(包括如何安装LDAP服务器/客户端)
  11. php 载入css就可以显示,如何在进度条加载后显示页面
  12. 创业者怎样掌握简便的创业机会
  13. 多模态大咖齐刷刷翻开小红书,明晚7点不见不散
  14. python连接数据库步骤_Python连接mysql数据库
  15. 叶子的离开,是因为风的追求,还是树的不挽留
  16. android 程序错乱,android – 安装时应用程序崩溃,错误sqlite3_...
  17. Luogu4116 Qtree3
  18. C语言实战之猜拳游戏
  19. 蓝桥杯练习 圆的面积
  20. 洛谷P4939 Agent2(树状数组差分)

热门文章

  1. java 中== 和equal的区别
  2. 解决:The server time zone value ‘�й���׼ʱ��‘ is unrecognized or represents more than one time zone.
  3. 自监督学习经典之作:DINO
  4. 特斯拉公布马斯克去年薪酬状况:工资5.6万美元 期权激励超过22亿美元
  5. 体育科技文献通报杂志体育科技文献通报杂志社体育科技文献通报编辑部2022年第6期目录
  6. linux系统处理excel,Apache POI处理Excel文档
  7. 升级Ubuntu造成RTL8125网卡驱动丢失
  8. 怎么进行finebi下载
  9. PostgreSQL安装异常:Problem running post-install step。
  10. 如何入门Python之Python基础教程详解