《算法概论》习题的6.10:数人头问题,给定 n 和 k,以及每个硬币人头(正面)朝上的概率p_1, p_2, ..., p_n,确定 n 枚独立的硬币同时落地后,恰好有 k 枚硬币朝上的概率。
O(nk)时间的算法好弄,但是下面冒出来这么个注释:事实上,除了本习题所列举的算法外,还有一个 O(n log^2 n) 时间的算法。
求教,那是什么算法?
首先声明一下,楼主是个坏人。好久没看这种算法题了,居然还是这么理论的。
脑细胞死了不知多少,唉。关键是看不懂啥叫O(nk),还Google了一把。
在O(NK)的算法里面,有重复计算的部分,这部分通过增加空间复杂度的方法,可以减少时间。算法是这样的,
设h(i,j)为抛出前i个硬币,出现j个正面的概率。于是有:
if j>i, then h(i,j)=0
else
h(i,j)=p_i*h(i-1,j-1)+(1-p_i)*h(i-1,j)
你仔细看看,就会发现h(2,1)被算了好多次,h(3,1), h(3,2)同样,只有h(n-1,k-1)被算的次数最少。通过增加空间保存h(i,j),就减少了时间。
我也只看出这个来,至于是不是o(N LOG^2 n)这个已经还给老师了。
O(nk)的解用就是这个转移方程,用上记忆化时间也一样是O(nk)。
@Chielo Newctle: 错误的,你仔细想想。
比如H(100,50)这个,他假设了计算 H(49,29)是O(49*29)的时间。
但是实际上H(49,29)就不需要O(49*29)这么多的时间。他在计算H(48,28)这个的时候,别人已经算过,他只要从空间中取出来,从Dictionary数组中取出h(48,28)的时间是一个常量,在时间复杂度计算中,常量时间是可以忽略的。
这个别人是H(49,30)或者H(50,29)或者H(49,28)
@爱编程的大叔:
2 # # + + + + +
1 # + + + + + #
0 # + + + + # #
@ 0 1 2 3 4 5 6
你不能忽视之前需要计算的项,比如上述计算 h(6, 2) 的情形,“+”表示需要进行的计算。所以,如果使用DP,至少需要计算 n*k - k^2 - 1 次才可以得到结果,明显超出 O(n log^2 n) 的上界。
我猜测能达到 O(n log^2 n) 时间的算法和组合数学有关系。
时间复杂度、空间复杂度
真是抱歉,问题没说清楚。时间复杂度,问题已改。
@Chielo Newctle:
看看这个吧,你会明白的:
算法时间复杂度计算:
http://wenku.baidu.com/link?url=t3xEacCEF-cJCO7oG51V6m73hPBFu9KpjPQ_r5RXgSpe92QdkbYfNLRTM3ETUot11-ySEkWRO0CAl2G_R-HjpIWXCAwKISGV60-RJe97uhm