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