Ruby 部分斐波那契和,如何提高性能?
我需要改进这个算法的性能。我相信答案在于皮萨诺时期的应用 该算法必须返回从f(m)到f(n)的fib数总和的最后一位 以下是我到目前为止的情况:Ruby 部分斐波那契和,如何提高性能?,ruby,fibonacci,Ruby,Fibonacci,我需要改进这个算法的性能。我相信答案在于皮萨诺时期的应用 该算法必须返回从f(m)到f(n)的fib数总和的最后一位 以下是我到目前为止的情况: def fib(n) a = [] a << 0 << 1 (n+1).times do |i| a << a[-1] + a[-2] end a[n] end def fib_partial_sum(m, n) if n == m
def fib(n)
a = []
a << 0 << 1
(n+1).times do |i|
a << a[-1] + a[-2]
end
a[n]
end
def fib_partial_sum(m, n)
if n == m
fib(m) % 10
else
m = fib(m + 1) - 1
n = fib(n + 2) - 1
(n - m) % 10
end
end
if __FILE__ == $0
m, n = gets.split().map(&:to_i)
puts "#{fib_partial_sum(m, n)}"
end
def fib(n)
a=[]
a以下只需要一次从零到最多[n,m+60].min之间的数字传递,其中m..n
是感兴趣的范围,并且具有最小的内存需求。它利用了@nloveladyallen的观察结果,即斐波那契数的最后一位具有60的周期性
代码
def fib_last(m,n)
n -= 60*((n-m)/60)
fib_sum(m,n) % 10
end
def fib_sum(m,n)
return nil if m < 0 || m > n
return n if n < 2
next_to_last, last = fib(m-1)
(m..n).reduce(0) do |tot,_|
current = next_to_last + last
next_to_last = last
last = current
tot + current
end
end
def fib(m)
next_to_last, last = -1, 1
0.upto(m).each do |n|
current = next_to_last + last
next_to_last, last = last, current
end
[next_to_last, last]
end
m, n = 6, 12
(n+1).times { |i| puts "#{i}: #{fib(i)}" }
0: [0, 0]
1: [0, 1]
2: [1, 1]
3: [1, 2]
4: [2, 3]
5: [3, 5]
6: [5, 8]
7: [8, 13]
8: [13, 21]
9: [21, 34]
10: [34, 55]
11: [55, 89]
12: [89, 144]
fib_last(6,12) #=> 4 (fib_sum(6,12) #=> 8 + 13 + 21 + 34 + 55 + 89 + 144 = 364)
fib_last(1,2) #=> 2 (fib_sum(1,2) #=> 1 + 1 = 2)
fib_last(1,3) #=> 4 (fib_sum(1,3) #=> 1 + 1 + 2 = 4)
fib_last(1,4) #=> 7 (fib_sum(1,4) #=> 1 + 1 + 2 + 3 = 7)
fib_last(2,3) #=> 3 (fib_sum(2,3) #=> 1 + 2 = 3)
这是一个很好的问题解决方案,它通过了所有的时间和内存限制。
这样你就不必计算一个大于f(60)的fib数值。它可以有效地处理非常大的输入
def fib(n)
a, b = 0, 1
(n-1).times do
a, b = b, (a + b) % 10
end
b
end
def fib_partial_sum(m, n)
if n == m
fib(m % 60)
else
m = m % 60
n = n % 60
m = fib(m + 1) - 1
n = fib(n + 2) - 1
(n - m) % 10
end
end
if __FILE__ == $0
m, n = gets.split().map(&:to_i)
puts "#{fib_partial_sum(m, n)}"
end
(最大使用时间:0.05/5.00,最大使用内存:8699904/536870912。)是否应启用此选项?除非是代码不起作用。标题表明是这样,但质疑性能。顺便问一下,您有理由在fib
上使用数组吗?你的函数基本上返回一个数字;使用两个临时变量而不是一个数组(它有分配/重新分配和垃圾收集的开销,还有更大的内存占用),可以很容易地做到这一点。斐波那契数的最后数字每60个数字重复一次,因此可以用n%60和m%60替换n和m。(你真的可以只使用最后一个数字序列的数组,但你可能正在尝试学习算法技术,所以这可能不是你想要的。)@matthewalexander它在输入上失败了,因为你只更改了fib_partial_sum
中的else
,在本例中n=m。将if
主体更改为fib(m%60)
,它应该可以工作。“非常感谢您的任何见解。”
也是不可取的。虽然对帮助表示感谢很好,但作为一本参考书而不是一个讨论板,有一种更正式的立场。把它想象成一本教科书或食谱,然后相应地写下来。欢迎一些熟悉和友好,但签名、问候和感谢不会被删除。输入1失败,输入1失败,输入1失败,输入3我卡里-非常感谢您的努力,请查看我的最新更新,了解我所寻求的解决方案。我有严格的时间和内存限制,我修改了代码,加入了@nloveladyallen对斐波那契数最后一位数字周期性的观察。
def fib(n)
a, b = 0, 1
(n-1).times do
a, b = b, (a + b) % 10
end
b
end
def fib_partial_sum(m, n)
if n == m
fib(m % 60)
else
m = m % 60
n = n % 60
m = fib(m + 1) - 1
n = fib(n + 2) - 1
(n - m) % 10
end
end
if __FILE__ == $0
m, n = gets.split().map(&:to_i)
puts "#{fib_partial_sum(m, n)}"
end