c语言用递归求奇数和,奇数正整数和的递归算法

让我建议你在Python中实现你的想法。您可能会惊讶地发现工作代码与伪代码非常相似。

这是原来的算法:

def sum_of_n_odds(n):

if n == 1:

return 1

else:

return sum_of_n_odds(n-1) + (2*n-1)

这是你写的一个:

def sum_of_odds_up_to_n(n):

if n == 1:

return 1

if n % 2 > 0: # this means n is odd

return n + sum_of_odds_up_to_n(n-1)

if n % 2 == 0: # this means it's even

return 0 + sum_of_odds_up_to_n(n-1)

这两种算法计算不同的东西。调用sum_of_n_odds(10)的结果与调用sum_of_odds_up_to_n(19)或sum_of_odds_up_to_n(20)的结果相同。通常,sum_of_odds_up_to_n(n)等于sum_of_n_odds((n+1)//2),其中//表示整数除法。

如果您有兴趣使您的实施更高效一点,我建议您省略最后的if条件,其中n % 2 == 0。整数是奇数或偶数,所以如果它不是奇数,它必须是偶数。

当n为奇数时,您可以通过递归调用sum_of_odds_up_to(n-2)来获得另一个性能增益。目前,你正在将一半的函数调用浪费在偶数上。

有了这两个方面的改进,代码变为:

def sum_of_odds_up_to_n(n):

if n <= 0:

return 0

if n % 2 == 0:

return sum_of_odds_up_to_n(n-1)

return n + sum_of_odds_up_to_n(n-2)

这是尾递归版本:

def sum_of_odds_up_to_n(n, partial=0):

if n <= 0:

return partial

if n % 2 == 0:

return sum_of_odds_up_to_n(n-1, partial)

return sum_of_odds_up_to_n(n-2, partial+n)

你不应该指望从上面的性能提升,因为Python没有优化用于尾递归。但是,你可以重写尾递归迭代为,其运行速度将更快,因为它不花时间对每个递归调用分配栈帧:

def sum_of_odds_up_to_n(n):

partial = 0

if n % 2 == 0:

n -= 1

while n > 0:

partial += n

n -= 2

return partial

最快的实现所有的依赖于数学洞察力。考虑总和:

1 + 3 + 5 + ... + (n-4) + (n-2) + n

观察,你可以配对的第一个元素与最后一个元素,倒数第二个元素的第二个元素,与倒数第三元素的第三个元素,依此类推:

(1 + n) + (3 + n-2) + (5 + n-4) + ...

这是很容易看到,这等于:

(n + 1) + (n + 1) + (n + 1) + ...

多少项(n + 1)有哪些?由于我们从原始序列中每次配对两个项目,因此(n + 1)序列中的项目数量是其中的一半。

您可以检查自己的原始序列是否有(n + 1)/2条款。 (提示:如果您为每个术语添加1,请参阅获得的结果。)

新序列的数量是该术语的一半,或(n + 1)/4。而在该序列的每个术语(n + 1),所以整个序列的总和:

(n + 1) * (n + 1)/4

产生的Python程序是这样的:

def sum_of_odds_up_to_n(n):

if n <= 0:

return 0

if n % 2 == 0:

n -= 1

return (n+1)*(n+1)//4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值