Scala:递归地找到数组

时间:2017-02-26 19:23:45

标签: scala

我是斯卡拉的新手。为了练习递归,我自己设定了查找数组最大值的任务。我的基本情况是长度为1的数组。对于每个递归传递,我比较数组值0和1的大小,消除较小的值直到满足基本情况。

  def max(m: Array[Int]): Int = {
      if (m.length == 1) m(0)
      else if (m(0) > m(1)) m.take(1)
      else m.take(0)
    return max(m)
  }

但是在repl中这没有返回任何内容(可能是无限循环)。我不明白为什么数组不会减少到长度1.我是否需要辅助内部函数或什么?

2 个答案:

答案 0 :(得分:4)

这绝对是一个无限循环,因为你递归调用max并传入相同的参数(在术语中,take不是修饰符)。

要回答问题的其余部分,您不需要需要内部帮助函数。

尝试将以下算法转换为Scala:

  • 如果列表为空,则抛出错误
  • 否则,如果列表中有一个元素返回其第一个元素
  • 否则
    • (递归)计算m.take(1)的最大值,调用此max_of_rest
    • 返回m(0)max_of_rest
    • 中较大的一个

在Scala中学习有趣的学习递归!

<强>附录

上述算法在产生正确答案的同时效率低下。考虑:

maximum([2, 4, 1, 10, 3])
  = max(2, maximum([4, 1, 10, 3]))
  = max(2, max(4, maximum([1, 10, 3])))
  = max(2, max(4, max(1, maximum([10, 3]))))
  = max(2, max(4, max(1, max(10, maximum([3])))))
  = max(2, max(4, max(1, max(10, 3))))
  = max(2, max(4, max(1, 10)))
  = max(2, max(4, 10))
  = max(2, 10)
  = 10

注意每个调用如何“堆积”在调用堆栈上,消耗大量额外内存。在这种情况下,使用尾递归公式要好得多。

maximum([2, 4, 1, 10, 3])
  = _maximum([4, 1, 10, 3], max(4, 2))
  = _maximum([1, 10, 3], max(1, 4))
  = _maximum([10, 3], max(10, 4))
  = _maximum([3], max(3, 10))
  = _maximum([], 10)
  = 10

现在在这个尾递归的情况下,正如Joost den Boer所指出的,你有第二个功能。你可以看到这个内部递归函数就像这样工作

_maximum(a, v) =
  if a is empty return v
  else return _maximum(a.take(1), max(a(0), v))

外部功能类似于

maximum(a) =
  if a is empty raise an error
  else return _maximum(a.take(1), a(0))

我故意不使用Scala语法,因此您可以尽情享受。玩得开心!

答案 1 :(得分:2)

m不会修改max(m)。因此,您使用与反复相同的数组调用scala> val m = Array(1, 2, 3, 4, 5); m: Array[Int] = Array(1, 2, 3, 4, 5) scala> m.take(1) res0: Array[Int] = Array(1) scala> m res1: Array[Int] = Array(1, 2, 3, 4, 5)

take()

另请注意,scala> m.take(0) res2: Array[Int] = Array() scala> m.take(3) res3: Array[Int] = Array(1, 2, 3) 完全不符合您的想法。

./bin/