谷歌访谈拼图

时间:2011-12-21 03:38:27

标签: algorithm probability counting

给定n个骰子,'a'侧和b中的每一个返回可以获得总和b的方式的数量。如何减少时间复杂度和空间复杂度? 这是在Google采访中被问到的,我不确定答案。

3 个答案:

答案 0 :(得分:7)

这要求您找到将b写为n正整数之和的方法的数量。答案是b部分n的{​​{3}}个(b-1 choose n-1)部分,a

现在,如果我们考虑到零件尺寸限制为x^b的约束,那么问题就会变得更加有趣。我建议使用compositions。答案将是产品(x+x^2+...+x^a)^n1的系数。为什么?因为对于每个骰子(骰子的单数),你有一个介于ax之间的数字,这由x^i的指数表示。当您从每个n条款中选择一个i时,这相当于该死亡中出现的数字b。指数的总和必须是你所追求的总和,即(x + x^2 + ... + x^a)^n = sum_{k1+k2+...+ka=n} (n multichoose k1,k2,...,ka) x^{k1+2*k2+...+a*ka}

我们甚至可以使用generating functions来简化问题:

ki >= 0

所有sum_{k1+k2+...+ka=n & k1+2*k2+...+a*ka=b} (n multichoose k1,k2,...,ka) 。所以答案是方法的数量是

{{1}}

答案 1 :(得分:0)

我会有一个数组hits[max + 1],它计算每个值的可能组合数。 maxn * a,当然hits[0]hits[n - 1]将保持为空。

愚蠢的方法是做n for-loop(每个骰子一个)并在hits中记录当前骰子总和的命中。

不那么愚蠢的方法是使用一些组合词,我写出每个有序 shuffle的组合数:

有1111(sum = 4)的1个组合 有4个组合1112(sum = 5)
共有4个组合1113(总和= 6)
...
有11 *(sum = 7)的4 * 3/2组合 ...
有12 *(总和= 10)的4 * 3 * 2组合 ...
aaaa(sum = n * a

的1种组合

你需要在for-loops中花费的时间少于愚蠢的解决方案 每次迭代都会得到很多命中,而不是使用哑法进行一次命中。

那些for循环只移动(n-1)分区分隔(1,2,3,4,...,a)。 分离可以在同一点上(例如,对于案例1111,它们都在1和2之间),但是你必须没有低于1或高于a的分离。

答案 2 :(得分:-2)

假设a足够大(具体为a> = b-n),则归结为

x1+x2+x3+...+xn=b

这是在'n'孩子中分发'b'糖果的典型问题。 如果你想避免0面临死亡,应该很容易看到

(y1+1)+(y2+1)...+(yn+1)=b
y1+y2+...+yn=b-n

所以一般解决方案     z1 + z2 + ... zk = n是     C(N + K-1,K-1)

在收到几个downvotes后编辑:

假设我们限制'a'即b-n> a, 我们可以将其表述为DP问题

dp[k][j] is no. of ways to get a sum of j using dices 1 to k inclusive
dp[1][j] is 0 if j>a or j==0 else 1

然后我们可以评估以下关系

from k = 2 to n
  from j = 1 to b
     from x = 1 to a
        dp[k][j] += dp[k-1][j-x] where x is from 1 to a at max and x<j

并且答案应该是dp [n] [b] 订单n * b和运行时间O(n * b * a)

的存储