算法之Python实现 - 003 : 换钱的方法数
【题目】给定数组arr,arr中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求组成aim的方法数。
【代码1】递归
import numpy as np def changemeans(arr,aim):
if len(arr)<0:
print("No coin provided for change!")
arr.sort()
arr.reverse()
m = process(arr,0,aim)
print('There are ',m,' ways!') def process(arr,idx,aim):
res = 0
i = 0
if aim == 0:
res = 1
else :
if idx == len(arr):
res = 0
else :
while arr[idx]*i <= aim:
res += process(arr,idx+1,aim - arr[idx]*i)
i += 1
return res # ===CALL === #
a = [5,10,25,1]
tar = 1000
changemeans(a,tar)
【代码2】改进递归(递归加入记忆搜索):时间复杂度O(N * aim2)
【原理】:例如按照题目中的a = [5,10,25,1],使用a[0]和a[1],利用[25,1]组成剩余的980元的可能性就是一种重复递归,假设利用[25,1]组成剩余的980元需要5秒钟,那么【代码1】需要搜索5*0+10*2,5*2+10*1,5*5 三次递归,【代码2】额外耗用了O((N+1)*(aim+1))的空间,但是只要三次寻址即可。
import numpy as np def changemeans(arr,aim):
if len(arr)<0:
print("No coin provided for change!")
arr.sort()
arr.reverse()
map = np.zeros((len(arr)+1,aim+1))
m = process(arr,0,aim,map)
print('There are ',m,' ways!') def process(arr,idx,aim,map):
res = 0
i = 0
if aim == 0:
res = 1
else :
if idx == len(arr):
res = 0
else :
while arr[idx]*i <= aim:
mapval = map[idx+1][aim- arr[idx]*i]
if mapval != 0:
if mapval == -1: mapval = 0
res += mapval
else:
res += process(arr,idx+1,aim - arr[idx]*i,map)
i += 1
if res == 0:
map[idx][aim] = -1
else :
map[idx][aim] = res
#print(':',int(map[idx][aim]),res)
return res # ===CALL === #
a = [5,10,25,1]
tar = 1000
changemeans(a,tar)
【代码3】:时间复杂度O(N * aim2)
import numpy as np def changemeans(arr,aim):
n = len(arr)
if n<=0:
print('No coin provided for exchange.')
j = 0
dp = np.zeros((n,aim+1)) for i in range(0,n):
dp[i][0] = 1 while j*arr[0]<= aim:
dp[0][j*arr[0]] = 1
j += 1 for i in range(1,n):
for j in range(1,aim+1):
num = 0
k = 0
while j-arr[i]*k >= 0:
num += dp[i-1][j-arr[i]*k]
k += 1
dp[i][j] = num print(dp[n-1][aim]) # ===CALL === #
a = [5,10,25,1]
tar = 1000
changemeans(a,tar)
【代码4】:
另外实际上算arr[0..i-1]的组成剩下的方法,只会从最少的那个钱币为下标的位置开始,因此可以改为:
import numpy as np def changemeans(arr,aim):
n = len(arr)
if n<=0:
print('No coin provided for exchange.')
j = 0
dp = np.zeros((n,aim+1)) for i in range(0,n):
dp[i][0] = 1 while j*arr[0]<= aim:
dp[0][j*arr[0]] = 1
j += 1 for i in range(1,n):
for j in range(min(arr)-1,aim+1):
num = 0
k = 0
while j-arr[i]*k >= 0:
num += dp[i-1][j-arr[i]*k]
k += 1
dp[i][j] = num print(dp[n-1][aim]) # ===CALL === #
a = [5,10,25,2]
tar = 1000
changemeans(a,tar)
算法之Python实现 - 003 : 换钱的方法数的更多相关文章
- 算法进阶面试题07——求子数组的最大异或和(前缀树)、换钱的方法数(递归改dp最全套路解说)、纸牌博弈、机器人行走问题
主要讲第五课的内容前缀树应用和第六课内容暴力递归改动态规划的最全步骤 第一题 给定一个数组,求子数组的最大异或和. 一个数组的异或和为,数组中所有的数异或起来的结果. 简单的前缀树应用 暴力方法: 先 ...
- [DP]换钱的方法数
题目三 给定数组arr, arr中所有的值都为整数且不重复.每个值代表一种面值的货币,每种面值的货币可以使用任意张,在给定一个整数aim代表要找的钱数,求换钱有多少种方法. 解法一 --暴力递归 用0 ...
- [程序员代码面试指南]递归和动态规划-换钱的方法数(DP,完全背包)
题目描述 给定arr,arr中所有的值都为正数且不重复.每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim,求组成aim的方法数. 解题思路 完全背包 和"求换钱的 ...
- 八大排序算法的 Python 实现
转载: 八大排序算法的 Python 实现 本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个 ...
- Python练习题 003:完全平方数
[Python练习题 003]一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少? --------------------------------------- ...
- 数据关联分析 association analysis (Aprior算法,python代码)
1基本概念 购物篮事务(market basket transaction),如下表,表中每一行对应一个事务,包含唯一标识TID,和购买的商品集合.本文介绍一种成为关联分析(association a ...
- 机器学习算法与Python实践之(四)支持向量机(SVM)实现
机器学习算法与Python实践之(四)支持向量机(SVM)实现 机器学习算法与Python实践之(四)支持向量机(SVM)实现 zouxy09@qq.com http://blog.csdn.net/ ...
- 机器学习算法与Python实践之(三)支持向量机(SVM)进阶
机器学习算法与Python实践之(三)支持向量机(SVM)进阶 机器学习算法与Python实践之(三)支持向量机(SVM)进阶 zouxy09@qq.com http://blog.csdn.net/ ...
- 机器学习算法与Python实践之(二)支持向量机(SVM)初级
机器学习算法与Python实践之(二)支持向量机(SVM)初级 机器学习算法与Python实践之(二)支持向量机(SVM)初级 zouxy09@qq.com http://blog.csdn.net/ ...
随机推荐
- Galaxian 小蜜蜂
发售年份 1979 平台 街机 开发商 南梦宫(Namco) 类型 射击 https://www.youtube.com/watch?v=XhYVcwhSWjI
- KiCad 一款强大的 BOM 和 装配图生成插件
KiCad 一款强大的 BOM 和 装配图生成插件 可以生成 BOM 和在线的图形. https://github.com/openscopeproject/InteractiveHtmlBom In ...
- pache tomcat慢速HTTP拒绝服务攻击安全问题解决办法
问题说明:HTTP协议的设计要求服务器在处理之前完全接收到请求.如果HTTP请求未完成,或者传输速率非常低,则服务器将保持其资源占用等待剩余的数据.如果服务器占用的资源太多,则会造成拒绝服务. 漏洞危 ...
- 18.22 sprintf函数功能
函数功能:把格式化的数据写入某个字符串 函数原型:int sprintf( char *buffer, const char *format [, argument] … ); 返回值:字符串长度(s ...
- 嵌入式C语言常见的错误
预处理的错误: #include “stdio.h” //引用符号错误 #inlcude <name> //自定义文件用 " " not find gcc -I ...
- DNS缓存服务器与转发服务器
DNS缓存服务器与转发服务器 什么是缓存服务器(cache-only) 缓存服务器只需要根区域解析库文件,不包含任何其它区域解析库文件,这样的服务器就叫着缓存服务器.这样的服务器只有缓存搜寻结果的功能 ...
- 数学模块_math
ceil 进一, 向上取整 floor 向下取整 pow(x, y) x的y次方 print(math.pow(2, 3)) # 8.0 sqrt(x) x的开平方(结果为浮点数) print(mat ...
- TensorFlow代码初识
直接看代码 import tensorflow as tf # tf.Variable生成的变量,每次迭代都会变化, # 这个变量也就是我们要去计算的结果,所以说你要计算什么,你是不是就把什么定义为V ...
- Redis深入学习笔记(六)Redis内存分配
Redis的高效可以说是轻量级的epoll模型和基于内存的读写共同组成的,关于epoll对于以前的select或者poll的性能优势这里不做介绍,本篇主要介绍领一个重点,Redis的内存分配原理. 获 ...
- linux centos7下mysql安装--韩国庆
首先我先给大家介绍下MariaDB和mysql的区别. 上图,“MySQL之父”的骨灰级程序员Monty,但是mysql被Oracle收购后,Monty又开始去发展另一条数据库的道路,并且以Monty ...