PossibleSums

1.假如你有数枚硬币,在已知这些硬币的面值和每种面值有几枚时,随机从这些硬币中取出几枚硬币可能的和有多少种?(谷歌笔试题)

  • 记硬币的面值为coins=[10,50,100],其相应面值的枚数为quantity=[1,2,1]
  • 则:

    • 50 = 50
    • 10 + 50 = 60
    • 50 + 100 = 150
    • 10 + 50 + 100 = 160
    • 50 + 50 = 100
    • 10 + 50 + 50 = 110
    • 50 + 50 + 100 = 200
    • 10 + 50 + 50 + 100 = 210
    • 10 = 10
    • 100 = 100
    • 10 + 100 = 110
  • 从上面可以看出来总共有9中不同的和.
  • 整理思路:从上面的求和过程可以看出,单个硬币的枚数依次加入到每一种和中,取不同的值,可以把最终的和的取值放在一个元素单一的数据结构类型中,如C++或者Python中的set数据类型。

    • 0 = 0
    • 10 = 10
    • iiiiiiiiiiiiiiiiiiii
    • 0 + 50 = 50
    • 10 + 50 = 60
    • iiiiiiiiiiiiiiiiiiiiiiiiiii
    • 0 + 50 = 50
    • 10 + 50 = 60
    • 50 + 50 = 100
    • 60 + 50 = 110
    • iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
    • 0 + 100 = 100
    • 10 + 100 = 110
    • 50 + 100 = 150
    • 60 + 100 = 160
    • 50 + 100 = 150
    • 60 + 100 = 160
    • 100 + 100 = 200
    • 110 + 100 = 210

    为了减少重复运算的次数,从数量最多的硬币面值开始迭代,每一枚硬币都对已经取得的所有和求和并放至保存和的容器中。

  • 验证代码(python)

    def possibleSums(coins, quantity):
    p=max(quantity)
    maxIndex=quantity.index(p)
    b=set([coins[maxIndex]*x for x in xrange(p+1)])
    for i in range(len(coins)):
        if i!=maxIndex:
            for j in xrange(quantity[i]):
                d=b.copy()
                for k in b:
                    d.add(k+coins[i])
                b=d
    return len(b)-1                
  • 提交代码(C++)

    int getMaxPos(std::vector<int>vec){
    int maxPos=0;
    int a=vec[maxPos];
    for(size_t i=1;i<vec.size();i++){
        if(a<vec[i]){
            maxPos=i;
            a=vec[maxPos];
        }
    }
    return maxPos;
    }
    int possibleSums(std::vector<int> coins, std::vector<int> quantity) {
        int maxPos=getMaxPos(quantity);
        int maxV=quantity[maxPos];
        std::set<int>sum;
        for(int i =0;i<maxV+1;i++){
            sum.insert(i*coins[maxPos]);
        }
        for(int i=0;i<coins.size();i++){
            if(i!=maxPos){
                for(int j=1;j<=quantity[i];j++){
                    std::set<int>temSum=sum;
                    for(std::set<int>::iterator it=sum.begin();it!=sum.end();it++){
                        temSum.insert(*it+coins[i]);
                    }
                    sum=temSum;
                }
            }
        }
        return (sum.size()-1);
    }

  • refer

[1] https://codefights.com/interview-practice/task/rMe9ypPJkXgk3MHhZ

[2] http://www.cplusplus.com/reference/set/set/operator=/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值