怎么样用一个比较优美的方法计算得到一个累加数组,如下
#测试用例:
[] => []
[0, -3, 5, 7] => [0, -3, 2, 9]
[1, 3, 5, 7] => [1, 4, 9, 16]
谢谢帮忙,先总结一下大家目前的劳动成果
a = [1,3,5,7]
# Method 1 from @fredwu @abitno => O(n)
a.inject([]) { |sum,e| sum << (sum[-1] || 0) + e }
# Method 2 from @luikore => O(n)
sum = 0
a.map {|e| sum += e }
# Method 3 from @nil => O(n^2)
a.length.times.map {|i| a[0..i].inject(:+)}
# Update Method 3 => O(n)
temp = 0
a.length.times.map {|i| temp = [temp, a[i]].inject(:+)}
//////////////////// 更新 /////////////////////// 第三种方法的好处是可以扩展为其他运算符号,这样累加或者累乘都可以解决了。
不过缺点是计算效率好像不怎么高,每次都是从头开始算,前面两个算法都是 O(n), 第三个方法是 O(n^2),对于一般的数组基本上没啥区别,如果是大数组,就要考虑下了。
给这个方法取个名字吧,想到了 Accumulation 这个单词,查了下 webster 词典,该词的英文意思是 Accumulation - increase or growth by addition especially when continuous or repeated 应该还算贴切,而且 acum 和 sum 还挺押韵的
def acum(a, init, &oper)
a.length.times.map {|i| a[0..i].inject(init, &oper)}
end
#测试用例
a = [1,3,5,7]
#累加(注意init应设为0)
p acum(a, 0, &:+) => [1, 4, 9, 16]
#累乘(注意init应设为1)
p acum(a, 1, &:*) => [1, 3, 15, 105]
也可以用在字符数组的累积合并中
a = %w[r u b y]
#字符串的累积合并
p acum(a, "", &:+) => ["r", "ru", "rub", "ruby"]
//////////////////// 更新 /////////////////////// 简单测试了下,对大数组,两种方法区别还是挺大的
class Array
def acum_add
sum = 0
self.map {|e| sum += e }
end
def acum(init=0, &oper)
self.length.times.map {|i| self[0..i].inject(init, &oper)}
end
end
(1..100).to_a.acum_add # => [Finished in 0.2-0.3s]
(1..100).to_a.acum(&:+) # => [Finished in 0.2-0.3s]
(1..10000).to_a.acum_add # => [Finished in 0.2-0.4s]
(1..10000).to_a.acum(&:+) # => [Finished in 8.8s] !!!!!
//////////////////// 更新 /////////////////////// 把 Method 3 改进了下,现在也是 O(n) 了,各取所长,不知道有没有到 O(logn) 的
class Array
def acum(init=0, &oper)
temp = init
self.length.times.map {|i| temp = [temp, self[i]].inject(init, &oper)}
end
end
(1..10000).to_a.acum(&:+) # => [Finished in 0.2-0.4s]