'''
Each new term in the Fibonacci sequence is generated by adding the previous two terms.
By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million,
find the sum of the even-valued terms.
不超过4000000的Fibonacci序列中所有偶数的和
'''
分析:
方案一:求出所有小于4000000的Fibonacci序列,然后对所有偶数进行求和
方案二:分析序列规律,两个偶数中间有两个奇数,所以可以在求值的时候,进行过滤求和
方案三:偶数等于前面奇数之和,那么把所有数累加后,除2得到的结果就是所有偶数的和,前提是4000000前的一项数是偶数,若为奇数,那么须额外处理
那么问题还是在求Fibonacci序列
给定第一项1,每二项1,以后每项的值为前两项之和
注:方案与解法不一一对应
解法一:# 取两个变量,需要在计算时进行累加
def even_Fibonacci_numbers(limit=4000000):
fir = 1
sec = 1
tmp = fir + sec
res = fir + sec
while tmp < limit:
if tmp % 2 == 0:
res += tmp
fir, sec = sec, tmp
tmp = fir + sec
return res
此方法,需要关注序列中做去处的两项的值的交换,但空间方面就节省了
解法二:#采用数组保存序列值
def even_Fibonacci_numbers(limit=4000000):
fi = [1,1]
tmp = sum(fi)
while tmp < limit:
fi.append(tmp)
tmp = fi[-2] + fi[-1]
return sum([i for i in fi if i % 2 == 0])
此方法,只需要关注累加的那一项是否超过界限,但用列表来保存增加的项。
若需要增加的项很多,可以先开辟一段空间,解法上需要做一下修改。
解法三:#取两个变量,累计所有和,然后分析得到的序列的奇偶性,并处理
def even_Fibonacci_numbers(limit=4000000):
while tmp < limit:
fir, sec = sec, tmp
res += sec
tmp = fir + sec
if res % 2 == 1:
res = (res - sec) / 2
else:
if sec % 2 == 0:
res /= 2
else:
res = (res - sec - fir) / 2
return res
此方法,最后分析处理,fir,sec只有三种可能的情况,奇奇,奇偶,偶奇
fir,sec:偶奇,得到的res为奇数,所以需要减去sec,得到的结果再除以2,得最终结果
fir,sec:奇奇,奇偶,得到的res均为偶数,故需要进一步判断,
若sec为偶数,那么将结果直接除以2即可
若sec为奇数,那么得到的结果需要减去fir和sec,然后将结果除以2,得最终结果
这里再引用一下别人的做法,依然是分析序列:这个解法算是方案二的求解。
x, y, x + y, x + 2y, 2x + 3y, 3x + 5y
这里,我们需要取的值是x+y,3x+5y
python表示:
def calcE(limit=4000000):
x = y = 1
res = 0
while (res < limit):
res += (x + y)
x, y = x + 2 * y, 2 * x + 3 * y
return res
这个解法是这些解法中运行速度最快的,也许解决当前这个问题足够了,但是并不正确
当改变限界为6*10**6时,会得到错误结果。
正确的表示:
def calcE(limit=4000000):
x = y = 1
res = 0
while res < limit and x < limit and y < limit:
res += (x + y)
x, y = x + 2 * y, 2 * x + 3 * y
return res
对于参与累计的值,必须满足之前所有的值都小于限界,一但某个值超过了限界,那么就必须结束累计。
这样得到的结果才会是正确的。
提一点,有人用数学方法,直接推导最后的结果,算法复杂度O(1)