(LeetCode 322) Coin Change

25 篇文章 0 订阅
23 篇文章 0 订阅

Q:
You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.

Example 1:
coins = [1, 2, 5], amount = 11
return 3 (11 = 5 + 5 + 1)

Example 2:
coins = [2], amount = 3
return -1.

Note:
You may assume that you have an infinite number of each kind of coin.

也就是给你一些面值的硬币,然后给你一个数,问这个数能不能由给你提供的面值累加得到,并且问需要的最少硬币个数。
每个面值的硬币假设有无限个。

solution:
哎,感觉自己还是太差,这么个问题也写了一个多少小时。
第一眼看到这个问题,我首先想到解法是BFS算法,已知coins中的最小值是 min ,那么我们遍历迭代的最高层数就是 maxf=amount/min ,如果到了这个层数还没有找到,那么就不能拆分。

  1. 保留两个队列,先将amount减去coins中的值,并压入到其中一个队列pq1中。
  2. 将pq1中的值一个个弹出,并减去coins中的面值,压入到pq2中。
  3. 将pq2中的值一个个弹出,并减去coins中的面值,压入到pq2中。
  4. 循环2、3步,直到弹出的值为0或者 迭代次数 >maxf ,如果是弹出值为0,那么返回2、3步迭代次数。否则返回-1。

当然也很容易想到,超时了,毕竟遍历数量是随层数增加指数增长的。

上网一查,发现大家用的都是动态规划DP,核心意思就是 dp[n]=min(dp[n],dp[ncoins[m]]+1) ,然后从dp[1]迭代到 dp[n] ,其实也好理解。但是我觉得这种方法时间消耗较高,大概是 O(nm)
我想了想,BFS算法经过剪枝后最多遍历次数也就是 n 次,所以还是用BFS算法写了。但是加入了剪枝操作,因为我发现它的时间复杂度过高是因为有重复的数值压入队列中,那么,使用一个数组来标记每一个压入值。如果当前压入值已经被标记,那么就不压入该值。这样一剪枝,那么重复的数值就不会出现了,那么最坏的遍历就是amount0,也就是遍历n次。

class Solution {
public:
    queue<int>pq1;
    queue<int>pq2;
    int coinChange(vector<int>& coins, int amount) {
        if(coins.size()==0)return -1;
        if(amount==0)return 0;
        int *flag =new int[amount];

        int min = coins[0];
        for(int i=0;i<coins.size();i++){
            if(coins[i]<min)
                min=coins[i];
                pq1.push(amount-coins[i]);
                if(amount-coins[i]>=0)flag[amount-coins[i]]=-1;
        }
        for(int j=1;j<=amount/min;j++){
            queue<int> &pq3=(j%2!=0)?pq1:pq2;
            queue<int> &pq4=(j%2!=0)?pq2:pq1;
            while(!pq3.empty()){
                int res = pq3.front();
                pq3.pop();
                if(res<0)continue;
                if(res==0)return j;
                for(int k=0;k<coins.size();k++){
                    if(flag[res-coins[k]]==-1||res-coins[k]<0) continue;
                    pq4.push(res-coins[k]);
                    flag[res-coins[k]]=-1;
                }
            }
        }
        return -1;
    }
};

事实证明,时间消耗比起DP确实小了很多。这个是116ms,DP是159ms。

Reference Link:
http://blog.csdn.net/sbitswc/article/details/50505003

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值