【问题标题】:Kadane's Algorithm in ScalaScala 中的 Kadane 算法
【发布时间】:2012-02-20 22:42:46
【问题描述】:

有没有人以函数式风格完成Kadane's algorithm 的 Scala 实现?

编辑说明: 链接上的定义发生了变化,导致该问题的答案无效——这说明了为什么问题(和答案)应该是独立的,而不是依赖于外部链接。这是原始定义:

在计算机科学中,最大子数组问题是在具有最大和的一维数字数组(包含至少一个正数)中找到连续子数组的任务。例如,对于值序列 -2、1、-3、4、-1、2、1、-5、4;和最大的连续子数组是 4, -1, 2, 1,总和为 6。

【问题讨论】:

    标签: scala functional-programming kadanes-algorithm


    【解决方案1】:

    如果允许空子数组或者输入数组不能都是负数,那该怎么办:

    numbers.scanLeft(0)((acc, n) => math.max(0, acc + n)).max
    

    或者,不满足上述条件(假设输入非空):

    numbers.tail.scanLeft(numbers.head)((acc, n) => (acc + n).max(n)).max
    

    【讨论】:

    • xs.tail.scanLeft(xs.head)((acc, x) => (acc+x).max(x)).max 如果所有都可能是负数。 :D
    • 最大子数组问题有两种表述,其中一种允许返回隐式总和为零的空子数组。顺便说一下,最大子数组的索引也必须返回。
    • 当 [-1] 时失败,预期结果为 -1 但给出 0。
    • @SuryaprakashPisay 如果 不允许空子数组,并且允许所有负数,是的。请参阅第一条评论以了解该案例的替代实现,但我将编辑答案以包含它。
    • 原来我改变了你的答案而不是我的。我希望你不介意——反正它是被接受的。
    【解决方案2】:

    我更喜欢折叠解决方案而不是扫描解决方案——尽管后者肯定更优雅。总之,

    numbers.foldLeft(0 -> 0) {
      case ((maxUpToHere, maxSoFar), n) =>
        val maxEndingHere = 0 max maxUpToHere + n
        maxEndingHere -> (maxEndingHere max maxSoFar)
    }._2
    

    【讨论】:

    • 如果数组包含负值,此解决方案将不起作用
    • @MoustafaMahmoud 嗯,肯定会的。我刚刚使用问题的维基百科链接上的示例对其进行了测试,它提供了预期的解决方案。你设想什么问题?
    • 当 [-1] 时失败,预期结果为 -1 但给出 0。
    • @SuryaprakashPisay 啊,我刚刚注意到我回复了您对错误答案的评论!在提出这个问题时,链接的 Wikipedia 文章指定输入数组将“包含至少一个正数”,因此 [-1] 是无效输入。见March 3, 2012
    【解决方案3】:

    以下代码返回开始和结束索引以及总和:

    
    import scala.math.Numeric.Implicits.infixNumericOps
    import scala.math.Ordering.Implicits.infixOrderingOps
    
    case class Sub[T: Numeric](start: Index, end: Index, sum: T)
    
    def maxSubSeq[T](arr: collection.IndexedSeq[T])(implicit n: Numeric[T]) =
      arr
        .view
        .zipWithIndex
        .scanLeft(Sub(-1, -1, n.zero)) {
          case (p, (x, i)) if p.sum > n.zero => Sub(p.start, i, p.sum + x)
          case (_, (x, i))                   => Sub(i, i, x)
        }
        .drop(1)
        .maxByOption(_.sum)
    

    【讨论】:

      猜你喜欢
      • 2020-03-13
      • 2011-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多