【问题标题】:Scala - Combining two sequences to consecutively increasing triplesScala - 将两个序列组合成连续增加的三元组
【发布时间】:2015-06-23 06:22:55
【问题描述】:

解决以下问题的好方法是什么?在命令式风格中,这可以在线性时间内完成。

给定两个排序序列p和q,f返回一个三元组序列r(或任何集合),其中r中的每个三元组(a,b,c),以下保持:

  1. (abc)
  2. 以下两项之一成立:
    • a,c 是两个连续元素p,b 在q
    • a,c 是两个连续元素q,b 在p

示例:考虑以下两个序列。

val p = Seq(1,4,5,7,8,9)
val q = Seq(2,3,6,7,8,10)

然后f(p,s) 计算以下序列:

Seq((1,2,4), (1,3,4), (5,6,7), (3,4,6), (3,5,6), (8,9,10))

当前解决方案:我觉得这个不是很优雅。我正在寻找更好的。

    def consecutiveTriplesOneWay(s1: Seq[Int], s2:Seq[Int]) = {
        for {
            i <- 0 until s1.size - 1 if s1(i) < s1(i+1)
            j <- 0 until s2.size if s1(i) < s2(j) &&  s2(j) < s1(i+1)
        } yield (s1(i), s2(j), s1(i+1))
    }

    def consecutiveTriples(s1: Seq[Int], s2:Seq[Int]) =
        consecutiveTriplesOneWay(s1, s2) ++ consecutiveTriplesOneWay(s2, s1)

    def main(args: Array[String]) {
        val p = Seq(1,4,5,7,8,9)
        val q = Seq(2,3,6,7,8,10)

        consecutiveTriples(p, q).foreach(println(_))
    }

编辑:我的命令式解决方案

def consecutiveTriplesOneWayImperative(s1: Seq[Int], s2:Seq[Int]) = {
    var i = 0
    var j = 0
    val triples = mutable.MutableList.empty[(Int,Int,Int)]
    while (i < s1.size - 1 && j < s2.size) {
        if (s1(i) < s2(j) && s2(j) < s1(i + 1)) {
            triples += ((s1(i), s2(j), s1(i + 1)))
            j += 1
        } else if (s1(i) >= s2(j))
            j += 1
        else
            i += 1
    }
    triples.toSeq
}

def consecutiveTriples(s1: Seq[Int], s2:Seq[Int]) = 
    consecutiveTriplesOneWayImperative(s1,s2) ++ 
            consecutiveTriplesOneWayImperative(s2,s1)

【问题讨论】:

  • 你试过什么?函数式风格如何让翻译命令式解决方案变得困难?您是否使用过典型的 while -> fold/recurse 方法?
  • 你有一些代码吗?因为这听起来像是一个练习,我们应该代替你解决它。
  • 这看起来像家庭作业。如果这是用命令式编写的,用户应该注意到 (3, 5, 6) 缺少作为有效答案。
  • @Karl:感谢您发现错字。 :D 不是作业。大学毕业很久了。
  • 我添加了我不太喜欢的当前解决方案。必须有一种更优雅的方式来做到这一点

标签: scala


【解决方案1】:

转换为 tailrec 的命令式解决方案。有点冗长但有效

def consecutiveTriplesRec(s1: Seq[Int], s2: Seq[Int]) = {
  @tailrec
  def consTriplesOneWay(left: Seq[Int], right: Seq[Int],
                        triples: Seq[(Int, Int, Int)]): Seq[(Int, Int, Int)] = {
    (left, right) match {
      case (l1 :: l2 :: ls, r :: rs) =>
        if (l1 < r && r < l2) consTriplesOneWay(left, rs, (l1, r, l2) +: triples)
        else if (l1 >= r) consTriplesOneWay(left, rs, triples)
        else consTriplesOneWay(l2 :: ls, right, triples)
      case _ => triples
    }
  }
  consTriplesOneWay(s1, s2, Nil) ++ consTriplesOneWay(s2, s1, Nil)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 2018-10-05
    • 1970-01-01
    相关资源
    最近更新 更多