配对算法 - 性能与二分搜索

时间:2015-04-21 10:42:28

标签: algorithm scala performance sum

我正在使用Scala实现一个算法,用于从单独的数组l1和l2中查找值x1和x2,使得x1 + x2 = t,其中t是某个目标值。

算法1逐个遍历l1和l2并检查x1 + x2 = t。在O(n ^ 2)中运行。 算法2对l2进行排序,然后对l1中的每个项目执行二进制搜索。据说在O(nlogn)中运行,但没有。为什么它比算法1运行得慢?

请注意,这是课程作业,我只是寻找线索。

算法1:

def hasPairSlow(l1: List[Int], l2: List[Int], target: Int): Option[Pair[Int,         Int]] = {
  l1 foreach { i => 
    l2 foreach { j => if (i+j == target) return Some(i -> j) } 
  }
  None
}

算法2:

def hasPair(l1: List[Int], l2: List[Int], target: Int): Option[Pair[Int, Int]]   = {
  val s2 = l2.sorted
  l1 foreach { i =>
    val p = checkPair(i, s2, target)
    if (p.isDefined) return Some(i, p.get)
  }
  None
}

private def checkPair(x: Int, l: List[Int], target: Int): Option[Int] = {
  val mid = l.length / 2
  if (mid == 0) { // Length == 1
    if (l.head + x == target) Some(l.head) else None
  } else {
    val candinate = l(mid)
    if (candinate + x == target) Some(candinate)
    else {
      val s = l.splitAt(mid)
      if (candinate + x > target) {
        checkPair(x, s._1, target)
      }
      else /* candinate + x < target */ {
        checkPair(x, s._2, target)
      } 
  }
}

2 个答案:

答案 0 :(得分:2)

val s = l.splitAt(mid)

splitAt函数遍历整个列表(如列表中的随机访问一样),因此您的第二个算法不会更好。由于元素访问和列表拆分所涉及的开销,情况更糟。

答案 1 :(得分:1)

抱歉,由于声誉低,我无法发表评论,但我很好奇你的意思是“跑得慢”?在最坏的情况下给出了两种算法的复杂性。即使n非常大,Alg1也很可能在时间上超出Alg2(例如在第一次迭代时找到答案)。