题解 | #换钱的最少货币数#

换钱的最少货币数

http://www.nowcoder.com/practice/3911a20b3f8743058214ceaa099eeb45

换钱的最少货币数

描述

给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。如果无解,请返回-1
示例1 
输入:[5,2,3],20
返回值:4
示例2
输入:[5,2,3],0
返回值:0

方法一

思路分析

本题可以使用动态规划的办法,设置二维数组$dp[i][j]$表示要凑成$aim=j$时的最少货币数,其中$i$代表可以使用的货币种类为:$arr[0]-arr[i-1]$,初始化当$aim=0$时最少货币数为0,如果使用$arr[i]$那么货币数为$dp[i][j-arr[i]]+1$,如果不使用货币$arr[i]$,那么$dp[i][j]=dp[i-1][j]$,由此得到状态转移方程。初始化当前可以使用的货币只有一种时,货币数为$dp[i][j]=dp[i][j-arr[0]]+1$;之后随着可以使用的货币种类的增加,货币数发生改变。由此回自上而下,从左到右填充数组,最后输出$dp[len(arr)-1][aim]$记为最少货币数。动态规划的优点时将之前找到的最少货币数记录下来,需要查找的时候直接比较。初始化数组第一行的值INT_MAX,转移方程如下:
dp[i][j]=\left\{ <br />             \begin{array}{**lr**}  <br />            dp[i][j-arr[i]]+1, & i=0.\\  <br />             min\{dp[i-1][j],   dp[i][j-arr[i]]+1\}, & 1\leq i.\\  <br />                <br />             \end{array}  <br />\right.

图解

给定实例,写出求解过程



核心代码

class Solution {
public:
    /**
     * 最少货币数
     * @param arr int整型vector the array
     * @param aim int整型 the target
     * @return int整型
     */
    int minMoney(vector<int>& arr, int aim) {
        // write code here
        int n=arr.size();
        if(n==0) return -1;
        if(aim==0) return 0;
        vector<vector<int>> dp(n,vector<int>(aim+1));//定义二维数组
        for(int j=1; j <= aim; j++)
		{
            dp[0][j] = INT_MAX;//填充第一行
            if(j-arr[0] >= 0 && dp[0][j-arr[0]] != INT_MAX )
			{
                dp[0][j] = dp[0][j-arr[0]] + 1;//dp[0][j-arr[0]]存储aim=j-arr[0]的最少货币数,并且只使用arr[0]
            }
        }
        
       int res = 0;
        for(int i=1; i < n; i++)
		{
           for(int j=1; j <=aim; j++)//自上而下,从左往右填充数组
		   {          
               res = INT_MAX;
                if(j-arr[i] >=0 && dp[i][j-arr[i]] != INT_MAX)
				{
                    res = dp[i][j-arr[i]] + 1;
                }
                dp[i][j] = min(res, dp[i-1][j]);//如果使用arr[i]那么货币数为dp[i][j-arr[i]] + 1,如果不适用货币arr[i],那么dp[i][j]=dp[i-1][j]
            }
        }
    return dp[n - 1][aim] != INT_MAX ? dp[n - 1][aim]:-1;
    }
};
复杂度分析
  • 时间复杂度:需要对二维数组进行填充,时间复杂度为$O(len(arr)*aim)$,时间复杂度与所给货币的数量以及目标值有关
  • 空间复杂度:需要设置一个二维数组存储过程中的最少货币数,因为时间复杂度$O(len(arr)*aim)$

方法二

思路分析

动态规划的方法,需要减小额外的内存空间,在方法一中,可以看到逐渐添加货币时,需要比较不添加该货币的最少货币数,此时需要与上一行的数字进行比较,压缩空间的办法是直接将比较后 的值更新到第一行。

图解


核心代码

	class Solution {
public:
    /**
     * 最少货币数
     * @param arr int整型vector the array
     * @param aim int整型 the target
     * @return int整型
     */
    int minMoney(vector<int>& arr, int aim) {
        // write code here
        int n=arr.size();
        if(n==0) return -1;
        if(aim==0) return 0;
        int minCoins = 0;
        int res = 0;
        vector<int>dp(aim+1);
        dp[0] = 0;
        for (int i = 1; i < aim + 1; ++i) //初始化数组
        {
            if (i - arr[0] >= 0 && dp[i - arr[0]] != aim)
            {
                dp[i] = dp[i - arr[0]] + 1;//填充第一行,只有一种货币
            }
            else
                dp[i] = aim;
        }

        for (int i = 1; i < n; ++i)
        {
            for (int j = 1; j < aim + 1; ++j)
            {
                res = aim;
                if (j - arr[i] >= 0 && dp[j - arr[i]] != aim)
                {
                    res = dp[j - arr[i]] + 1;//逐渐增加货币,然后寻找最小值
                }
                dp[j] = res <= dp[j] ? res : dp[j];
            }
        }

        minCoins = dp[aim];
        return minCoins == aim ? -1 : minCoins;
    }
};
复杂度分析
  • 时间复杂度:需要填充更新数组,时间复杂度同方法一一样,$O(len(arr)*aim)$
  • 空间复杂度:设置一维数组,空间复杂度为$O(aim)$


全部评论

相关推荐

27届学院本誓死冲击...:自我评价和校园经历全删了,荣誉经历只留奖学金,项目也全得换都不如外卖
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 长得好看会提高面试通过率吗? #
3136次浏览 43人参与
# HR最不可信的一句话是__ #
1021次浏览 32人参与
# MiniMax求职进展汇总 #
24899次浏览 321人参与
# 春招至今,你的战绩如何? #
14766次浏览 137人参与
# AI面会问哪些问题? #
893次浏览 22人参与
# 你的实习产出是真实的还是包装的? #
2704次浏览 52人参与
# 巨人网络春招 #
11484次浏览 224人参与
# 沪漂/北漂你觉得哪个更苦? #
1235次浏览 38人参与
# 你做过最难的笔试是哪家公司 #
1131次浏览 20人参与
# AI时代,哪个岗位还有“活路” #
2684次浏览 49人参与
# XX请雇我工作 #
51147次浏览 171人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
7966次浏览 43人参与
# 简历第一个项目做什么 #
32073次浏览 357人参与
# 简历中的项目经历要怎么写? #
310908次浏览 4257人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152832次浏览 889人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187556次浏览 1123人参与
# AI时代,哪些岗位最容易被淘汰 #
64539次浏览 864人参与
# 如果重来一次你还会读研吗 #
229974次浏览 2011人参与
# 投格力的你,拿到offer了吗? #
178254次浏览 891人参与
# 你怎么看待AI面试 #
180654次浏览 1296人参与
# 正在春招的你,也参与了去年秋招吗? #
364172次浏览 2641人参与
# 腾讯音乐求职进展汇总 #
160822次浏览 1114人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务