找钱方式:递归,循环的解法

题目:给定一个金额m,以及几种钱币面值(比如1,2,5),求m有多少种找钱方式

解答:

a(m, c): 金额m的找钱方式,此时最大钱币面值为c

a(m, c) = sigma( a(m - k*c, next_c) ); k=0~m/c, next_c=比c小的下一个面值的钱币,比如c=5, next_c = 2

按照以上递推式,可以写出递归函数:

int exchangeWays(int money, int maxCurIndex = currencyNum - 1)
{
    if (money == 0) return 1;
    if (maxCurIndex == -1) return 0;
    int ways = 0;
    int maxCur = currency[maxCurIndex];
    for (int i = 0; i * maxCur <= money; i++)
        ways += exchangeWays(money - i * maxCur, maxCurIndex - 1);
    return ways;
}

这种解法的复杂度很高,O(m^(c的个数))

循环解法1:

有几个c就有几层循环,复杂度也是O(m^(c的个数))

int exchangeWaysIter(int money)
{
    int ways = 0;
    for (int i = 0; i * currency[2] <= money; i++)
    {
        money -= i * currency[2];
        for (int j = 0; j * currency[1] <= money ; j++)
        {
            money -= j * currency[1];
            for (int k = 0; k * currency[0] <= money; k++)//if currency[0] is 1, we can delete this loop
            {
                if (money == k * currency[0])
                    ++ways;
            }
            money += j * currency[1];
        }
        money += i * currency[2];
    }
    return ways;
}

重新观察递推式,我们可以得出循环解法2:

int exchangeWaysIter2(int money)
{
    vector<int> ways(money + 1);//ways(i) : sum equals i, exchange ways
    ways[0] = 1;
    for (int i = 0; i < currencyNum; i++)
    {
        for (int j = 0; j + currency[i] <= money; j++)
        {
            if (ways[j])
                ways[j + currency[i]] += ways[j];
        }
    }
    return ways[money];
}

时间复杂度为O(m*(c的个数)),空间复杂度为O(m)

一下就降低了时间复杂度。

时间: 2024-10-21 11:12:17

找钱方式:递归,循环的解法的相关文章

【剑指offer】递归循环两种方式反转链表

转载请注明出处:http://blog.csdn.net/ns_code/article/details/25737023 本文分别用非递归和递归两种方式实现了链表的反转,在九度OJ上AC. 题目描述: 输入一个链表,反转链表后,输出链表的所有元素.(hint : 请务必使用链表) 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000):代表将要输入的链表的个数.输入的第二行包含n个整数t(0<=t<=1000000)

二叉树的三种遍历方式的循环和递归的实现方式

///////////////////头文件:BST.h//////////////////////// #ifndef BST_H #define BST_H #include "StdAfx.h" #include<iostream> #include<stack> template<typename DataType> class BST { public: class Node { public: Node(int data=0):m_dat

linux shell for循环解决递归循环目录结构

今天总结一下关于linux shell里的递归循环的问题起因是一个群友在群里的提问问的是怎么把有或多或少空目录的几个文件移动走的问题归根结底就是一个递归循环的问题 如果之前接触过c语言之类的编程语言.那么这个很好理解就是通过函数来不断的自己调用自己这种方法有一个很大的弊端就是需要很多资源比如有一种进程调用的 fork 炸弹 就是自调用搞的 接下来我就贴一下代码然后简单的讲解一下 #!/bin/sh . /etc/plus.lib a() {     for file  in `ls $1`   

递归 循环 比较

算法分析: 循环算法和递归算法 无论时间效率还是空间效率都是前者高.递归算法在运行时,函数调用保存现场.开辟运行资源.返回回收资源都需要耗时.递归算法的参数表面是一个变量,实际上市一个栈. 结论1: 递归确实是一些复杂的问题处理起来简单明了,但是,就效率而言,递归算法的实现往往比循环算法耗费更多的时间和存储空间,也限制了递归的深度.所以,在具体的实现中,应尽可能把递归算法转换为等价的循环算法,以提高算法的时空效率. 相应问题,如给一个整数,从低位到高位输出各位的数字. 结论2: 由于递归算法的实

C# TreeView,递归循环数据加载到treeView1中

TblAreaBLL bll = new TblAreaBLL(); private void button1_Click(object sender, EventArgs e) { LoadDataToTree(this.treeView1.Nodes, bll.GetTblAreaListByID(0)); } private void LoadDataToTree(TreeNodeCollection treeNode, List<TblArea> list) { foreach (Tb

Java 螺旋数组的实现方式-一个循环实现哦

随着编程的学习和工作,感触越来越深的,就是如何做好对需求的理解.那么在学习的过程中,就是如何将一个实际问题,转化成计算机语言去实现.我觉得我的这方面的能力很是欠缺啊. 今天分享一下一个螺旋数组例子的分析: 贴上code: package excesize; /* * 螺旋数组: * 4 * 1 2 3 4 * 12 13 14 5 * 11 16 15 6 * 10 9 8 7 */ public class LuoxuanArray { public static void main(Stri

HDU 1005矩阵快速幂解法 循环节解法

循环节解法: 对于公式 f[n] = A * f[n-1] + B * f[n-2]; 后者只有7 * 7 = 49 种可能,为什么这么说,因为对于f[n-1] 或者 f[n-2] 的取值只有 0,1,2,3,4,5,6 这7个数,A,B又是固定的,所以就只有49种可能值了.由该关系式得知每一项只与前两项发生关系,所以当连续的两项在前面出现过,由于公式不变,那么后面得到的一定是跟前面相重复的.所以这个时候循环节就出现了,注意循环节并不一定会是开始的 1,1:但1,1一定可以作为一个循环节,只不过

记一次nodejs 爬虫(利用递归循环nightmare)

记一次nodejs 爬虫(利用递归循环nightmare) 新手,欢迎交流 目标网站 这里的网址很有规律,方便我们获取图书列表的url nightmare几个主要的api 具体参考:http://www.manongjc.com/detail/8-roxmpabfhewimht.html .goto(url,options) url:目标网站 options:伪造头部信息 .wait(callback[selector]) 这个方法会重复调用,直到 return true, 可以传入选择器,如:

算法:两种方式(递归/循环)实现二分查找

程序由Golang实现,代码如下: 1.使用递归实现二分查找 //使用递归进行二分查找 func binarySearchTest() { //二分查找的数组必须是已经排好序的 nums := []int{1, 3, 5, 6, 7, 10, 12, 15, 17, 18, 19, 20, 21} value := 2 var index int = searchIndex(nums, value) fmt.Println("index:", index) } //在nums中查找元素