问题
I am expressing the algorithms in pseudo code. I'm just wondering if my design works just as well as the original one displayed below. The algorithm is supposed to compute the sum of n odd positive integers.
This is how the algorithm should look:
procedure sumofodds(n:positive integer)
if n = 1
return 1
else
return sumofodds(n-1) + (2n-1)
This is how i designed my algorithm:
procedure odd(n: positive integer)
if n = 1
return 1
if n % 2 > 0
return n + odd(n-1) // this means n is odd
if n % 2 = 0
return 0 + odd(n-1) // this means its even
回答1:
One small improvement that might help is defining it with tail recursion. Tail recursion happens when the very last thing to execute is the recursive call. To make this tail recursive, use a helper method and pass the running sum as a parameter. I'm pretty sure the pseudo code below is tail recursive since, regardless of the result of the (if odd) check, the final step is the recursive call (the math happens before the recursive call).
procedure SumOdds(n)
return SumOddsHelper(n, 0)
procedure SumOddsHelper(n, sum)
if n = 1 return 1
if n is odd return SumOddsHelper(n-1, sum + n)
else return SumOddsHelper(n-1, sum)
回答2:
Your algorithm is not the same as the original.
The original computes the sum of the first n odd numbers.
Your algorithm computes the sum of all the odd numbers in the range 1..n.
So for an input of n=3, the first algorithm will compute 1+3+5, while your algorithm will compute 1+3.
(If you want a quicker way, then the formula n*n computes the sum of the first n odd numbers)
回答3:
Let me suggest that you implement your idea in Python. You may be surprised to see that the working code is very similar to pseudocode.
This is the original algorithm:
def sum_of_n_odds(n):
if n == 1:
return 1
else:
return sum_of_n_odds(n-1) + (2*n-1)
And this is the one you wrote:
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)
These two algorithms compute different things. Calling sum_of_n_odds(10)
yields the same result as calling sum_of_odds_up_to_n(19)
or sum_of_odds_up_to_n(20)
. In general, sum_of_odds_up_to_n(n)
is equivalent to sum_of_n_odds((n+1)//2)
, where //
means integer division.
If you're interested in making your implementation a little more efficient, I suggest that you omit the final if
condition, where n % 2 == 0
. An integer is either odd or even, so if it isn't odd, it must be even.
You can get another performance gain by making the recursive call sum_of_odds_up_to(n-2)
when n
is odd. Currently you are wasting half of your function calls on even numbers.
With these two improvements, the code becomes:
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)
And this is the tail-recursive version:
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)
You should not expect performance gains from the above because Python does not optimize for tail recursion. However, you can rewrite tail recursion as iteration, which will run faster because it doesn't spend time allocating a stack frame for each recursive call:
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
The fastest implementation of all relies on mathematical insight. Consider the sum:
1 + 3 + 5 + ... + (n-4) + (n-2) + n
Observe that you can pair the first element with the last element, the second element with the second last element, the third element with the third last element, and so on:
(1 + n) + (3 + n-2) + (5 + n-4) + ...
It is easy to see that this is equal to:
(n + 1) + (n + 1) + (n + 1) + ...
How many terms (n + 1)
are there? Since we're pairing up two terms at a time from the original sequence, there are half as many terms in the (n + 1)
sequence.
You can check for yourself that the original sequence has (n + 1) / 2
terms. (Hint: see what you get if you add 1 to every term.)
The new sequence has half as many terms as that, or (n + 1) / 4
. And each term in the sequence is (n + 1)
, so the sum of the whole sequence is:
(n + 1) * (n + 1) / 4
The resulting Python program is this:
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
来源:https://stackoverflow.com/questions/27325974/recursive-algorithm-for-the-sum-of-odd-number-positive-integers