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=/

c++14 ## 目描述 给定一个由 $n$ 条指令组成的程序,这些指令由一个具有单个整数寄存器 $A$ 的处理器执行,初始值为 $0$。每条指令是以下两种类型之一: - $\texttt{+ v}$ —— 执行 $A := A + v$; - $\texttt{= v}$ —— 执行 $A := v$。 程序中的指令从 $1$ 到 $n$ 编号。每条指令 $i$ 初始时间戳为 $i$。 有些指令被标记为 **异步**。如果指令 $i$ 是异步的,其时间戳可以更改为任何大于 $i$ 的 **实数**。 在所有时间戳调整之后,所有时间戳必须互不相同。处理器随后按时间戳递增的顺序执行指令。 确定在执行所有指令后,考虑所有可能的异步指令时间戳选择,$A$ 可以得到的不同的最终值的数量。 ## 输入格式 第一行包含一个整数 $n$,表示程序中的指令数量($1 \le n \le 2000$)。 接下来的 $n$ 行中,第 $i$ 行描述指令 $i$,包含三个标记。第一个标记是 $\texttt{+}$ 或 $\texttt{=}$,表示指令的类型。第二个标记是一个整数 $v$,表示指令的参数($1 \le v \le 500$)。最后,第三个标记是 $\texttt{async}$(如果指令被标记为异步)或 $\texttt{sync}$(否则)。 ## 输出格式 输出执行程序后 $A$ 可以取到的不同最终值的数量。 ## 输入输出样例 #1 ### 输入 #1 ``` 3 + 1 sync = 2 async + 3 async ``` ### 输出 #1 ``` 2 ``` ## 输入输出样例 #2 ### 输入 #2 ``` 10 = 7 async + 3 async + 5 sync + 3 async = 1 sync + 9 async + 10 async + 1 sync + 3 async + 4 sync ``` ### 输出 #2 ``` 30 ``` ## 说明/提示 在第一个测试中,程序执行从指令 $1$ 将 $A$ 设置为 $1$ 开始。然后,指令 $2$ 和 $3$ 按以下两种顺序之一执行: - 如果 $\texttt{= 2}$ 在 $\texttt{+ 3}$ 之前执行,$A$ 将等于 $5$; - 如果 $\texttt{+ 3}$ 在 $\texttt{= 2}$ 之前执行,$A$ 将等于 $2$。 因此,最后 $A$ 有两个可能的值:$5$ 和 $2$。
11-30
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值