给定n个骰子,'a'侧和b中的每一个返回可以获得总和b的方式的数量。如何减少时间复杂度和空间复杂度? 这是在Google采访中被问到的,我不确定答案。
答案 0 :(得分:7)
这要求您找到将b
写为n
正整数之和的方法的数量。答案是b
部分n
的{{3}}个(b-1 choose n-1)
部分,a
。
现在,如果我们考虑到零件尺寸限制为x^b
的约束,那么问题就会变得更加有趣。我建议使用compositions。答案将是产品(x+x^2+...+x^a)^n
中1
的系数。为什么?因为对于每个骰子(骰子的单数),你有一个介于a
和x
之间的数字,这由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]
,它计算每个值的可能组合数。 max
为n * 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
)
你需要在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)
的存储