【问题标题】:Analysis of the running time of concatconcat运行时间分析
【发布时间】:2018-08-17 16:29:13
【问题描述】:

这是 Richard Bird 用 Haskell 进行函数式思考 (p. 158) 中的一个例子。有人可以解释一下 1、2、3 和 4 背后的原因吗?

编辑。 我理解从第一个定义形成的前 3 个方程。对于 1.,为什么是求和?它与 T(++)(n, m) = Θ(n) 有什么关系? 对于第二个定义,我理解前两个陈述。第三个(2.),为什么是 k+n? 对于 3. 和 4. 我完全迷路了


首先考虑以下两个concat的定义:

concat xss= foldr (++) [] xss 
concat' xss = foldl (++) [] xss 

如果 xss 是一个有限列表,这两个定义是等价的。假设 xss 是长度为 m 的列表,其中列表的长度均为 n。那么第一个定义给出了

T(concat)(m, n) = T(foldr (++) [])(m, n),
T(foldr (++) [])(0, n) = Θ(1), 
T(foldr (++) [])(m+1, n) = T(++)(n, mn) + T(foldr (++) [])(m, n). 

估计 T(++)(n, mn) 的出现是因为长度为 n 的列表与长度为 mn 的列表连接在一起。由于 T(++)(n, m) = Θ(n),我们得到

1. T(foldr (++) [])(m,n) = Σ_{k=0}^{m} Θ(n) = Θ(mn)

对于 concat 的第二个定义,我们有

T(concat')(m, n) = T(foldl (++))(0, m, n),  
T(foldl (++))(k, 0, n) = O(1), 
2. T(foldl (++))(k, m+1, n) = T(++)(k, n) + T(foldl (++))(k+n, m, n).

附加参数 k 指的是 foldl 的第二个参数中累积列表的长度。这次我们获得了

3. T(foldl (++)) (k,m,n) = Σ_{j=0}{m-1} Θ(k+jn) = Θ(k+m^2n)

因此

4. T(concat')(m, n) = Θ(m_2 n)

【问题讨论】:

  • 我认为您应该详细说明您不清楚的地方。在我看来,您发布的内容已经解释了 1..4 背后的原因。如果您想要/需要更多信息,提供更多信息会有所帮助。例如。 “在 X 之前我什么都明白。接下来的步骤要求 Y——为什么 Y 应该持有?”
  • 我编辑了我的原始帖子。
  • 不那么冗长的符号可能会有所帮助。例如,对于 #1,f(m+1, n) = n + f(m, n)。等价: f(m) = n + f(m − 1) 其中 n 不变。你能看到你是如何将 f 重写为求和的吗?

标签: haskell functional-programming time-complexity


【解决方案1】:

对于 1.,为什么是求和?它与T(++)(n, m) = Θ(n) 有何联系?

求和来自归纳定义。考虑这个独立的定义

g(0,n) = something
g(m+1,n) = f(m,n) + g(m,n)

通过归纳,我们得到

g(m,m)
= f(m-1,n) + g(m-1,n)
= f(m-1,n) + f(m-2,n) + g(m-2,n)
= f(m-1,n) + f(m-2,n) + f(m-3,n) + g(m-3,n)
= f(m-1,n) + f(m-2,n) + f(m-3,n) + ... + f(m-m,n) + g(m-m,n)
= f(m-1,n) + f(m-2,n) + f(m-3,n) + ... + f(m-m,n) + something

因此,结果是 f(n,x) 的总和,其中 x 变化,加上最后一项 something

在原始定义中,g(m,n)T(foldr (++) [])(m, n),而 f(m,n) = T(++)(n, mn)。渐近地,最后一项无关紧要。

对于第二个定义,我理解前两个陈述。 第三个(2.),为什么是k+n?

在计算foldl (++) x ys 时,假设x 是一个长度为k 的列表,ys 是一个长度为m+1 的列表列表,其元素的长度为n

现在,递归 foldl 方程是:

foldl (++) x (y:ys) = foldl (++) (x++y) ys

递归调用的成本包括(A)temp = x++y 的成本,即T(++)(k, n),和(B)foldl (++) temp ys 的成本。对于 (B),temp 的长度现在是 length x + length y = k+n,而 ys 的长度是 mn 不受影响)。

所以,我们得到

T(foldl (++))(k, m+1, n) 
= A           + B
= T(++)(k, n) + T(foldl (++))(k+n, m, n).

对于 3. 和 4. 我完全迷失了

在 3. 中,我们对术语 T(++)(k, n)k 进行求和,就像我们对 1. 所做的那样。注意k 每次递归都会增加n,所以我们得到

T(++)(k, n) + T(++)(k+n, n) + T(++)(k+n+n, n) + ...
= Σ_{j=0}{m-1} T(++)(k+jn, n)
= Σ_{j=0}{m-1} Θ(k+jn) 
= Θ(k+m^2 n)

在 4. 中,我们选择 k=0,因为在 concat' 的定义中,我们最初选择长度为 0x=[]。所以,只有Θ(m^2 n) 存活下来。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-30
    • 1970-01-01
    • 1970-01-01
    • 2019-03-13
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多