Scala:确定多项式上+操作的两个不同实现的时间复杂度

时间:2014-07-23 11:37:29

标签: scala time-complexity

让我们说多项式可以看作是从指数到系数的映射。例如,x ^ 3 - 2x + 5可以用地图Map(0 -> 5, 1 -> -2, 3 -> 1)表示。我在Scala中有一个类Poly,它将多项式表示为映射。到现在为止还挺好。现在假设我在多项式上有两个+运算的实现。我想确定每种情况下+操作的时间复杂度,并找出两种实现中哪一种更有效。实现如下:

根据+

Poly上实施foldLeft操作
class Poly(terms0: Map[Int, Double]) {

  def this(bindings: (Int, Double)*) = this(bindings.toMap)

  val terms = terms0 withDefaultValue 0.0

  def + (other: Poly) = new Poly((other.terms foldLeft terms)(addTerm))

  def addTerm(terms: Map[Int, Double], term: (Int, Double)) = {
    val (exp, coeff) = term
    terms + (exp -> (coeff + terms(exp)))
  }

  override def toString = (for ((exp, coeff) <- terms.toList.sorted.reverse) 
    yield coeff + "x^" + exp) mkString " + "
}

根据+Poly

++上实施map操作
class Poly(terms0: Map[Int, Double]) {

  def this(bindings: (Int, Double)*) = this(bindings.toMap)

  val terms = terms0 withDefaultValue 0.0

  def + (other: Poly) = new Poly(terms ++ (other.terms map adjust))

  def adjust(term: (Int, Double)): (Int, Double) = {
    val (exp, coeff) = term
    exp -> (coeff + terms(exp))
  }

  override def toString = (for ((exp, coeff) <- terms.toList.sorted.reverse) 
    yield coeff + "x^" + exp) mkString " + "
}

到目前为止我做了什么

对于第一个版本,由于HashMap上的+操作需要有效的常量(eC)时间(根据这些performance characteristics),terms + (exp -> (coeff + terms(exp)))需要eC时间,因此{{1需要eC时间。因此,我们可以得出结论addTerm上的+操作需要(几乎?)线性时间,对吗?

对于第二个版本,假设Polyterms分别由n和m个元素组成。 other.terms需要eC时间,因此adjust需要(几乎?)O(m)时间。因此,other.terms map adjust需要O(n)+ O(m)时间,对吗?

那么哪种实施更有效?更正/建议吗?

1 个答案:

答案 0 :(得分:0)

他们应该在所添加的元素数量中有效地采用线性时间。您对第一个版本的分析是正确的,第二个版本中唯一的错误是++不是O(n)+ O(m),而是O(m)中的有效线性。 ++是反复执行+的简写,因此两个版本差异不大。

但是,merged中定义的HashMap方法可以为您完成所有这些:

def + (other: Poly) = new Poly(terms.merged(other.terms) { (x, y) =>
  (x._1, x._2 + y._2)
})

但是要求terms的类型为HashMap,这会使withDefaultValue无法使用,因为它不会返回HashMap

相关问题