我是斯卡拉的新手。为了练习递归,我自己设定了查找数组最大值的任务。我的基本情况是长度为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.我是否需要辅助内部函数或什么?
答案 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/