【问题标题】:How to find Max difference in a list/array in scala using recursion?如何使用递归在scala中找到列表/数组中的最大差异?
【发布时间】:2018-02-07 18:33:39
【问题描述】:

我是 Scala 的初学者,我正在尝试解决与此类似的问题。

https://www.geeksforgeeks.org/maximum-difference-between-two-elements/

我已经编写了该站点中编写的代码的 Scala 版本。这是我的代码:

object stock{
def getMaxP(Li:List[Int]):Int={

var max_diff=Li(1)-Li(0)
var min_ele=Li(0)

for(i<-0 until Li.length){      
  if(Li(i)-min_ele>max_diff) max_diff=Li(i)-min_ele
  if(Li(i)<min_ele) min_ele=Li(i)
}

max_diff  
}

def main(args:Array[String]){
val li=List(10, 7, 5, 8, 11, 9)
println(getMaxP(li))
}

}

上面的代码有效。但我想使用递归来解决它,我更喜欢使用 listname.tail 函数。我可以将 s_p_y.tai​​l 传递给递归函数(因为 s_p_y 是一个列表)并解决它,但我不知道如何实现。

这是我在网上找到的一个示例代码,它使用递归来查找最大元素。

def max2(ints: List[Int]): Int = { 
@tailrec
def maxAccum2(ints: List[Int], theMax: Int): Int = {
  if (ints.isEmpty) {
    return theMax
  } else {
    val newMax = if (ints.head > theMax) ints.head else theMax
    maxAccum2(ints.tail, newMax)
  }
}
maxAccum2(ints, 0)
}

} 

【问题讨论】:

  • 哇,这很难读!神秘的名字,下划线,没有缩进。
  • 编辑了问题,使其更具可读性。
  • 3 个闭合的花括号,中间没有一个开口,在相同的 x 位置上不是缩进。表达式之间的空格也有助于阅读。但迈出了第一步。

标签: scala recursion


【解决方案1】:

典型的模式是集合上的模式匹配:

@annotation.tailrec
def getMaxp (li: List[Int], min: Int, dmax: Int): Int = li match {
    case Nil => dmax ???
    case x :: rest => getMaxP (rest, ???, ???)
}

def main(args:Array[String]){
    val li = List (10, 7, 5, 8, 11, 9)
    println (getMaxp (li, ???, ???))
}

空的情况是什么 - 可能在列表的末尾,或者因为初始列表是空的?

getMaxp 的参数 2 和 3 必须以某种方式与最小值、最大值和 x (li(0)) 相关。

您可能会调用其他函数,当然,您必须就地编写这些函数,以避免中间值使空间混乱。

在现实生活中,为了方便调用方法,你可以提供一个易于调用的接口,并在内部处理起始阶段并使用内部函数,以确保选择正确的起始值:

def getMaxp (li: List[Int]): Int = li match {

    @annotation.tailrec
    def getMaxp (li: List[Int], min: Int, dmax:Int): Int = li match {
        case Nil => ???
        case x :: rest => getMaxP (rest, ???, ???)
    }
    getMaxP (rest, ???, ???)
}

def main(args:Array[String]){
    val li = List (10, 7, 5, 8, 11, 9)
    println (getMaxp (li))
}

【讨论】:

  • 我不明白如何进行这项工作。你能让它更简单吗?
  • @Kyuukei:我们看看第一个代码,是吗?如果您有一个空列表,那么返回 maxdiff 的合理方法是什么?那么,您在迭代代码中返回什么?那你的最小值是多少?
【解决方案2】:

解决这个问题的直接方法是使用标准库中提供的方法。

List(2,5,10,6,4,8,1).combinations(2).map{case List(a,b) => b-a}.max //res0 = 8

但是当您尝试使用递归时,这里有一个递归方法,它本身使用内部递归方法。

// find the maximum difference between any 2 numbers in a List[Int]
// (always: laterNumber - earlierNumer)
def maxDiff(li: List[Int], mx: Int = Int.MinValue): Int = {

  // test all subsequent elements against the current head
  def loop(subList: List[Int], subMax:Int = mx): Int =
    if (subList.isEmpty) subMax
    else loop(subList.tail, subMax max subList.head - li.head)

  if (li.isEmpty) mx  //all done
  else maxDiff(li.tail, loop(li.tail))
}

用法:

maxDiff(List(7, 9, 5, 6, 3, 2))  //res1: Int = 2

不需要var

【讨论】:

  • 这太棒了!你能告诉我“subMax max subList.head - li.head”是什么意思吗?我不熟悉这种 Scala 语法。
  • 也可以这样写:subMax.max(subList.head - li.head)loop()调用的第二个参数要么是subMax的值,要么是li的第一个元素减去的值subList 的第一个元素。取两者中较大的值。
【解决方案3】:

感谢@user 未知的回答。这就是我使用您的方法解决问题的方法。如果我能以任何方式改进我的代码,请告诉我。

object stock {


  def getMaxp(li: List[Int], maxd: Int, min: Int): Int = li match {
    case Nil => maxd
    case x :: rest => {
      var lmaxd: Int = maxd
      var lmin: Int = min
      if (x-min > maxd) lmaxd = x - min
      if (x < min) lmin = x
      getMaxp(rest, lmaxd, lmin)
    }
  }


  def main(args:Array[String]){
    val li =List(10, 7, 5, 8, 11, 9)
    val min=li(0)
    val maxd=li(1)-li(0)
    println (getMaxp(li,maxd,min))
  }

}

【讨论】:

  • 有经验的 Scala 程序员(即使是中级程序员)不要使用var。它几乎从来不需要。此外,每个if 都应该有一个else
  • 那我该如何更改我的代码?我不能使用 val,因为我会重新分配给 val 错误。
  • 不要计算成为递归调用参数的变量。根据需要编写参数:if (x-min &gt; maxd) getMaxp(rest, x-min, min) else if (x &lt; min) getMaxp(rest, maxd, x) else ...
  • 或者(更准确地说):getMaxp(rest, maxd.max(x-min), x.min(min))
猜你喜欢
  • 1970-01-01
  • 2018-06-22
  • 1970-01-01
  • 1970-01-01
  • 2020-11-25
  • 2018-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多